Skip to content

Commit 56da114

Browse files
takujicamc314
andauthored
fix(linter/react/jsx-handler-names): do not detect the function name within the inline-function's body block (#13456)
This PR fixes a behavior of `react/jsx-handler-names` rule incompatible with that of the eslint-version. ## Fixed difference with the eslint version With the configuration below: ```json { "checkInlineFunction": true, "checkLocalVariables": true } ``` the eslint version of `react/jsx-handler-names` rule treats the following code as invalid. ```tsx <TestComponent onChange={() => { handleChange() }} /> ``` But the current oxc version finds `handleChange` to be an event handler name and considers this code to be correct. Along with this change, the diagnostic messages are also modified because the event handler name is not always available, and replaced "invalid" with "bad" to be in accordance with the eslint-version's message ID`badHandlerName` and `badPropKey`. --------- Co-authored-by: Cameron Clark <cameron.clark@hey.com>
1 parent 48fde64 commit 56da114

File tree

2 files changed

+41
-8
lines changed

2 files changed

+41
-8
lines changed

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

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,16 @@ use serde_json::Value;
1515
fn bad_handler_name_diagnostic(
1616
span: Span,
1717
prop_key: &str,
18-
handler_name: &str,
18+
handler_name: Option<CompactStr>,
1919
handler_prefix: &str,
2020
) -> OxcDiagnostic {
21-
OxcDiagnostic::warn(format!("Invalid handler name: {handler_name}"))
21+
OxcDiagnostic::warn(
22+
if let Some(handler_name) = handler_name {
23+
format!("Invalid handler name: {handler_name}")
24+
} else {
25+
"Bad handler name".to_string()
26+
},
27+
)
2228
.with_help(format!(
2329
"Handler function for {prop_key} prop key must be a camelCase name beginning with \'{handler_prefix}\' only"
2430
))
@@ -28,11 +34,15 @@ fn bad_handler_name_diagnostic(
2834
fn bad_handler_prop_name_diagnostic(
2935
span: Span,
3036
prop_key: &str,
31-
prop_value: &str,
37+
prop_value: Option<CompactStr>,
3238
handler_prop_prefix: &str,
3339
) -> OxcDiagnostic {
3440
OxcDiagnostic::warn(format!("Invalid handler prop name: {prop_key}"))
35-
.with_help(format!("Prop key for {prop_value} must begin with \'{handler_prop_prefix}\'"))
41+
.with_help(if let Some(prop_value) = prop_value {
42+
format!("Prop key for {prop_value} must begin with \'{handler_prop_prefix}\'")
43+
} else {
44+
format!("Prop key must begin with \'{handler_prop_prefix}\'")
45+
})
3646
.with_label(span)
3747
}
3848

@@ -302,19 +312,19 @@ impl Rule for JsxHandlerNames {
302312
.map_or(Some(false), |v| self.event_handler_regex.as_ref().map(|r| r.is_match(v)));
303313

304314
match (prop_value, prop_is_event_handler, is_handler_name_correct) {
305-
(Some(value), Some(true), Some(false)) => {
315+
(value, Some(true), Some(false)) => {
306316
ctx.diagnostic(bad_handler_name_diagnostic(
307317
expression_container.span,
308318
prop_key,
309-
&value,
319+
value,
310320
&self.event_handler_prefixes,
311321
));
312322
}
313-
(Some(value), Some(false), Some(true)) => {
323+
(value, Some(false), Some(true)) => {
314324
ctx.diagnostic(bad_handler_prop_name_diagnostic(
315325
prop_span,
316326
prop_key,
317-
&value,
327+
value,
318328
&self.event_handler_prop_prefixes,
319329
));
320330
}
@@ -396,6 +406,12 @@ fn test_normalize_handler_name() {
396406
fn extract_callee_name_from_arrow_function<'a>(
397407
arrow_function: &'a ArrowFunctionExpression<'a>,
398408
) -> Option<&'a str> {
409+
if !arrow_function.expression {
410+
// Ignore arrow functions with block bodies like `() => { this.handleChange() }`.
411+
// The event handler name can only be extracted from arrow functions
412+
// with a single expression body, such as `() => this.handleChange()`.
413+
return None;
414+
}
399415
let Some(Statement::ExpressionStatement(stmt)) = arrow_function.body.statements.first() else {
400416
return None;
401417
};
@@ -454,6 +470,12 @@ fn test() {
454470
"<TestComponent onChange={() => handleChange()} />",
455471
Some(serde_json::json!([{ "checkInlineFunction": true, "checkLocalVariables": true }])),
456472
),
473+
(
474+
"<TestComponent onChange={() => { handleChange() }} />",
475+
Some(
476+
serde_json::json!([{ "checkInlineFunction": true, "checkLocalVariables": false }]),
477+
),
478+
),
457479
(
458480
"<TestComponent onChange={() => this.handleChange()} />",
459481
Some(serde_json::json!([{ "checkInlineFunction": true }])),
@@ -565,6 +587,10 @@ fn test() {
565587
"<TestComponent whenChange={() => handleChange()} />",
566588
Some(serde_json::json!([{ "checkInlineFunction": true, "checkLocalVariables": true }])),
567589
),
590+
(
591+
"<TestComponent onChange={() => { handleChange() }} />",
592+
Some(serde_json::json!([{ "checkInlineFunction": true, "checkLocalVariables": true }])),
593+
),
568594
(
569595
"<TestComponent onChange={handleChange} />",
570596
Some(

crates/oxc_linter/src/snapshots/react_jsx_handler_names.snap

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,13 @@ source: crates/oxc_linter/src/tester.rs
9292
╰────
9393
help: Prop key for handleChange must begin with 'on'
9494

95+
⚠ eslint-plugin-react(jsx-handler-names): Bad handler name
96+
╭─[jsx_handler_names.tsx:1:25]
97+
1 │ <TestComponent onChange={() => { handleChange() }} />
98+
· ──────────────────────────
99+
╰────
100+
help: Handler function for onChange prop key must be a camelCase name beginning with 'handle' only
101+
95102
⚠ eslint-plugin-react(jsx-handler-names): Invalid handler prop name: onChange
96103
╭─[jsx_handler_names.tsx:1:16]
97104
1 │ <TestComponent onChange={handleChange} />

0 commit comments

Comments
 (0)