mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 04:08:41 +00:00
fix(linter): move exhaustive-deps to react (#7251)
@Boshen lemme know if this is incorrect, but i noticed that `rules-of-hooks` lives inside `react` not `react-hooks`1f2a6c666f/crates/oxc_linter/src/config/rules.rs (L291-L292)1f2a6c666f/crates/oxc_linter/src/options/filter.rs (L254)
This commit is contained in:
parent
216d533b01
commit
ff2a1d4937
3 changed files with 270 additions and 260 deletions
|
|
@ -240,6 +240,7 @@ mod jest {
|
|||
mod react {
|
||||
pub mod button_has_type;
|
||||
pub mod checked_requires_onchange_or_readonly;
|
||||
pub mod exhaustive_deps;
|
||||
pub mod iframe_missing_sandbox;
|
||||
pub mod jsx_boolean_value;
|
||||
pub mod jsx_curly_brace_presence;
|
||||
|
|
@ -506,10 +507,6 @@ mod node {
|
|||
pub mod no_new_require;
|
||||
}
|
||||
|
||||
mod react_hooks {
|
||||
pub mod exhaustive_deps;
|
||||
}
|
||||
|
||||
oxc_macros::declare_all_lint_rules! {
|
||||
// import::no_deprecated,
|
||||
// import::no_unused_modules,
|
||||
|
|
@ -795,6 +792,7 @@ oxc_macros::declare_all_lint_rules! {
|
|||
promise::valid_params,
|
||||
react::button_has_type,
|
||||
react::checked_requires_onchange_or_readonly,
|
||||
react::exhaustive_deps,
|
||||
react::iframe_missing_sandbox,
|
||||
react::jsx_boolean_value,
|
||||
react::jsx_curly_brace_presence,
|
||||
|
|
@ -806,8 +804,8 @@ oxc_macros::declare_all_lint_rules! {
|
|||
react::jsx_no_useless_fragment,
|
||||
react::jsx_props_no_spread_multi,
|
||||
react::no_children_prop,
|
||||
react::no_danger,
|
||||
react::no_danger_with_children,
|
||||
react::no_danger,
|
||||
react::no_direct_mutation_state,
|
||||
react::no_find_dom_node,
|
||||
react::no_is_mounted,
|
||||
|
|
@ -962,5 +960,4 @@ oxc_macros::declare_all_lint_rules! {
|
|||
vitest::prefer_to_be_object,
|
||||
vitest::prefer_to_be_truthy,
|
||||
vitest::require_local_test_context_for_concurrent_snapshots,
|
||||
react_hooks::exhaustive_deps,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,10 +29,13 @@ use crate::{
|
|||
AstNode,
|
||||
};
|
||||
|
||||
const SCOPE: &str = "eslint-plugin-react-hooks";
|
||||
|
||||
fn missing_callback_diagnostic(hook_name: &str, span: Span) -> OxcDiagnostic {
|
||||
OxcDiagnostic::warn(format!("React hook {hook_name} requires an effect callback."))
|
||||
.with_label(span)
|
||||
.with_help("Did you forget to pass a callback to the hook?")
|
||||
.with_error_code_scope(SCOPE)
|
||||
}
|
||||
|
||||
fn dependency_array_required_diagnostic(hook_name: &str, span: Span) -> OxcDiagnostic {
|
||||
|
|
@ -49,12 +52,14 @@ fn unknown_dependencies_diagnostic(hook_name: &str, span: Span) -> OxcDiagnostic
|
|||
))
|
||||
.with_help("Pass an inline function instead.")
|
||||
.with_label(span)
|
||||
.with_error_code_scope(SCOPE)
|
||||
}
|
||||
|
||||
fn async_effect_diagnostic(span: Span) -> OxcDiagnostic {
|
||||
OxcDiagnostic::warn("Effect callbacks are synchronous to prevent race conditions.")
|
||||
.with_label(span)
|
||||
.with_help("Consider putting the asynchronous code inside a function and calling it from the effect.")
|
||||
.with_error_code_scope(SCOPE)
|
||||
}
|
||||
|
||||
fn missing_dependency_diagnostic(hook_name: &str, deps: &[String], span: Span) -> OxcDiagnostic {
|
||||
|
|
@ -79,6 +84,7 @@ fn missing_dependency_diagnostic(hook_name: &str, deps: &[String], span: Span) -
|
|||
})
|
||||
.with_label(span)
|
||||
.with_help("Either include it or remove the dependency array.")
|
||||
.with_error_code_scope(SCOPE)
|
||||
}
|
||||
|
||||
fn unnecessary_dependency_diagnostic(hook_name: &str, dep_name: &str, span: Span) -> OxcDiagnostic {
|
||||
|
|
@ -92,13 +98,14 @@ fn dependency_array_not_array_literal_diagnostic(hook_name: &str, span: Span) ->
|
|||
"React Hook {hook_name} was passed a dependency list that is not an array literal. This means we can't statically verify whether you've passed the correct dependencies."
|
||||
))
|
||||
.with_label(span)
|
||||
.with_help("Use an array literal as the second argument.")
|
||||
.with_help("Use an array literal as the second argument.") .with_error_code_scope(SCOPE)
|
||||
}
|
||||
|
||||
fn literal_in_dependency_array_diagnostic(span: Span) -> OxcDiagnostic {
|
||||
OxcDiagnostic::warn("The literal is not a valid dependency because it never changes.")
|
||||
.with_label(span)
|
||||
.with_help("Remove the literal from the array.")
|
||||
.with_error_code_scope(SCOPE)
|
||||
}
|
||||
|
||||
fn complex_expression_in_dependency_array_diagnostic(hook_name: &str, span: Span) -> OxcDiagnostic {
|
||||
|
|
@ -107,6 +114,7 @@ fn complex_expression_in_dependency_array_diagnostic(hook_name: &str, span: Span
|
|||
))
|
||||
.with_label(span)
|
||||
.with_help("Extract the expression to a separate variable so it can be statically checked.")
|
||||
.with_error_code_scope(SCOPE)
|
||||
}
|
||||
|
||||
fn dependency_changes_on_every_render_diagnostic(hook_name: &str, span: Span) -> OxcDiagnostic {
|
||||
|
|
@ -115,6 +123,7 @@ fn dependency_changes_on_every_render_diagnostic(hook_name: &str, span: Span) ->
|
|||
))
|
||||
.with_label(span)
|
||||
.with_help("Try memoizing this variable with `useRef` or `useCallback`.")
|
||||
.with_error_code_scope(SCOPE)
|
||||
}
|
||||
|
||||
fn unnecessary_outer_scope_dependency_diagnostic(
|
||||
|
|
@ -127,6 +136,7 @@ fn unnecessary_outer_scope_dependency_diagnostic(
|
|||
))
|
||||
.with_label(span)
|
||||
.with_help("Consider removing it from the dependency array. Outer scope values like aren't valid dependencies because mutating them doesn't re-render the component.")
|
||||
.with_error_code_scope(SCOPE)
|
||||
}
|
||||
|
||||
fn infinite_rerender_call_to_set_state_diagnostic(hook_name: &str, span: Span) -> OxcDiagnostic {
|
||||
|
|
@ -135,12 +145,14 @@ fn infinite_rerender_call_to_set_state_diagnostic(hook_name: &str, span: Span) -
|
|||
))
|
||||
.with_label(span)
|
||||
.with_help("Consider adding an empty list of dependencies to make it clear which values are intended to be stable.")
|
||||
.with_error_code_scope(SCOPE)
|
||||
}
|
||||
|
||||
fn ref_accessed_directly_in_effect_cleanup_diagnostic(span: Span) -> OxcDiagnostic {
|
||||
OxcDiagnostic::warn("The ref's value `.current` is accessed directly in the effect cleanup function.")
|
||||
.with_label(span)
|
||||
.with_help("The ref value will likely have changed by the time this effect cleanup function runs. If this ref points to a node rendered by react, copy it to a variable inside the effect and use that variable in the cleanup function.")
|
||||
.with_error_code_scope(SCOPE)
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
|
|
@ -226,7 +238,7 @@ impl Rule for ExhaustiveDeps {
|
|||
Argument::SpreadElement(_) => {
|
||||
ctx.diagnostic(unknown_dependencies_diagnostic(
|
||||
hook_name.as_str(),
|
||||
call_expr.callee.span(),
|
||||
callback_node.span(),
|
||||
));
|
||||
None
|
||||
}
|
||||
|
|
@ -312,7 +324,7 @@ impl Rule for ExhaustiveDeps {
|
|||
_ => {
|
||||
ctx.diagnostic(unknown_dependencies_diagnostic(
|
||||
hook_name.as_str(),
|
||||
call_expr.callee.span(),
|
||||
callback_node.span(),
|
||||
));
|
||||
None
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue