Skip to content

Commit 46cceb8

Browse files
committed
fix(linter/rules-of-hooks): correctly place primary span to fix disable directive (#14237)
fixes #14233
1 parent 50f7a1c commit 46cceb8

File tree

4 files changed

+128
-42
lines changed

4 files changed

+128
-42
lines changed

apps/oxlint/fixtures/disable_directive_issue_13311/.oxlintrc.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
},
66
"rules": {
77
"react/exhaustive-deps": "warn",
8+
"react/rules-of-hooks": "error",
89
"typescript/no-unsafe-declaration-merging": "error"
910
}
1011
}

apps/oxlint/fixtures/disable_directive_issue_13311/test.jsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,15 @@ function Component() {
1212
return null;
1313
}
1414

15+
// Test case for issue #14233 - disable directive not working for rules-of-hooks
16+
function useMostRelevantBreakdownType(params, filters) {
17+
// Helper function that starts with "use" but isn't a React hook
18+
console.log(params, filters);
19+
}
20+
21+
const cleanBreakdownParams = (cleanedParams, filters) => {
22+
// this isn't a react hook
23+
// oxlint-disable-next-line react-hooks/rules-of-hooks
24+
useMostRelevantBreakdownType(cleanedParams, filters);
25+
}
26+

crates/oxc_linter/src/rules/react/rules_of_hooks.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use oxc_cfg::{
1010
};
1111
use oxc_macros::declare_oxc_lint;
1212
use oxc_semantic::{AstNodes, NodeId};
13+
use oxc_span::GetSpan;
1314
use oxc_syntax::operator::AssignmentOperator;
1415

1516
use crate::{
@@ -24,14 +25,22 @@ mod diagnostics {
2425
use oxc_span::Span;
2526
const SCOPE: &str = "eslint-plugin-react-hooks";
2627

27-
pub(super) fn function_error(span: Span, hook_name: &str, func_name: &str) -> OxcDiagnostic {
28+
pub(super) fn function_error(
29+
react_hook_span: Span,
30+
outer_function_span: Span,
31+
hook_name: &str,
32+
func_name: &str,
33+
) -> OxcDiagnostic {
2834
OxcDiagnostic::warn(format!(
2935
"React Hook {hook_name:?} is called in function {func_name:?} that is neither \
3036
a React function component nor a custom React Hook function. \
3137
React component names must start with an uppercase letter. \
3238
React Hook names must start with the word \"use\".",
3339
))
34-
.with_label(span)
40+
.with_labels(vec![
41+
react_hook_span.primary_label("Hook is called here"),
42+
outer_function_span.label("Outer function"),
43+
])
3544
.with_error_code_scope(SCOPE)
3645
}
3746

@@ -202,6 +211,7 @@ impl Rule for RulesOfHooks {
202211
if !is_react_component_or_hook_name(&id.name) =>
203212
{
204213
return ctx.diagnostic(diagnostics::function_error(
214+
call.callee.span(),
205215
id.span,
206216
hook_name,
207217
id.name.as_str(),
@@ -247,6 +257,7 @@ impl Rule for RulesOfHooks {
247257
// }
248258
if ident.is_some_and(|name| !is_react_component_or_hook_name(&name)) {
249259
return ctx.diagnostic(diagnostics::function_error(
260+
call.callee.span(),
250261
*span,
251262
hook_name,
252263
"Anonymous",

0 commit comments

Comments
 (0)