Skip to content

Commit

Permalink
fix(linter): move exhaustive-deps to react (#7251)
Browse files Browse the repository at this point in the history
  • Loading branch information
camc314 committed Nov 14, 2024
1 parent 216d533 commit ff2a1d4
Show file tree
Hide file tree
Showing 3 changed files with 270 additions and 260 deletions.
9 changes: 3 additions & 6 deletions crates/oxc_linter/src/rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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,
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 {
Expand All @@ -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 {
Expand All @@ -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 {
Expand All @@ -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 {
Expand All @@ -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(
Expand All @@ -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 {
Expand All @@ -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)]
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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
}
Expand Down
Loading

0 comments on commit ff2a1d4

Please sign in to comment.