diff --git a/crates/oxc_linter/src/rules/react/button_has_type.rs b/crates/oxc_linter/src/rules/react/button_has_type.rs
index 0ec17e3933bab..bdddd89074105 100644
--- a/crates/oxc_linter/src/rules/react/button_has_type.rs
+++ b/crates/oxc_linter/src/rules/react/button_has_type.rs
@@ -23,9 +23,11 @@ fn missing_type_prop(span: Span) -> OxcDiagnostic {
.with_label(span)
}
-fn invalid_type_prop(span: Span) -> OxcDiagnostic {
+fn invalid_type_prop(span: Span, allowed_types: &str) -> OxcDiagnostic {
OxcDiagnostic::warn("`button` elements must have a valid `type` attribute.")
- .with_help("Change the `type` attribute to one of the allowed values: `button`, `submit`, or `reset`.")
+ .with_help(format!(
+ "Change the `type` attribute to one of the allowed values: {allowed_types}."
+ ))
.with_label(span)
}
@@ -95,7 +97,11 @@ impl Rule for ButtonHasType {
},
|button_type_prop| {
if !self.is_valid_button_type_prop(button_type_prop) {
- ctx.diagnostic(invalid_type_prop(button_type_prop.span()));
+ let allowed_types = self.allowed_types_message();
+ ctx.diagnostic(invalid_type_prop(
+ button_type_prop.span(),
+ &allowed_types,
+ ));
}
},
);
@@ -130,7 +136,11 @@ impl Rule for ButtonHasType {
|type_prop| {
if !self.is_valid_button_type_prop_expression(&type_prop.value)
{
- ctx.diagnostic(invalid_type_prop(type_prop.span));
+ let allowed_types = self.allowed_types_message();
+ ctx.diagnostic(invalid_type_prop(
+ type_prop.span,
+ &allowed_types,
+ ));
}
},
);
@@ -165,6 +175,29 @@ impl Rule for ButtonHasType {
}
impl ButtonHasType {
+ fn allowed_types_message(&self) -> String {
+ let mut types = Vec::new();
+ if self.button {
+ types.push("`button`");
+ }
+ if self.submit {
+ types.push("`submit`");
+ }
+ if self.reset {
+ types.push("`reset`");
+ }
+
+ match types.len() {
+ 0 => String::new(),
+ 1 => types[0].to_string(),
+ 2 => format!("{} or {}", types[0], types[1]),
+ _ => {
+ let last = types.pop().unwrap();
+ format!("{}, or {}", types.join(", "), last)
+ }
+ }
+ }
+
fn is_valid_button_type_prop(&self, item: &JSXAttributeItem) -> bool {
match get_prop_value(item) {
Some(JSXAttributeValue::ExpressionContainer(container)) => {
@@ -243,6 +276,10 @@ fn test() {
r#"React.createElement("button", {type: "button"})"#,
Some(serde_json::json!([{ "reset": false }])),
),
+ (
+ r#"React.createElement("button", {type: "button"})"#,
+ Some(serde_json::json!([{ "reset": false, "submit": false }])),
+ ),
(
r#"
function MyComponent(): ReactElement {
@@ -312,6 +349,10 @@ fn test() {
r#"React.createElement("button", {type: condition ? "reset" : "button"})"#,
Some(serde_json::json!([{ "reset": false }])),
),
+ (
+ r#"React.createElement("button", {type: condition ? "reset" : "button"})"#,
+ Some(serde_json::json!([{ "reset": false, "submit": false }])),
+ ),
(r#"Foo.createElement("button")"#, None),
(
r"function Button({ type, ...extraProps }) { const button = type; return ; }",
diff --git a/crates/oxc_linter/src/snapshots/react_button_has_type.snap b/crates/oxc_linter/src/snapshots/react_button_has_type.snap
index 909314b508ac1..7642da6afc0c4 100644
--- a/crates/oxc_linter/src/snapshots/react_button_has_type.snap
+++ b/crates/oxc_linter/src/snapshots/react_button_has_type.snap
@@ -55,7 +55,7 @@ source: crates/oxc_linter/src/tester.rs
1 │
· ────────────
╰────
- help: Change the `type` attribute to one of the allowed values: `button`, `submit`, or `reset`.
+ help: Change the `type` attribute to one of the allowed values: `button` or `submit`.
⚠ eslint-plugin-react(button-has-type): `button` elements must have a valid `type` attribute.
╭─[button_has_type.tsx:1:9]
@@ -76,7 +76,7 @@ source: crates/oxc_linter/src/tester.rs
1 │
· ─────────────────────────────────────
╰────
- help: Change the `type` attribute to one of the allowed values: `button`, `submit`, or `reset`.
+ help: Change the `type` attribute to one of the allowed values: `button` or `submit`.
⚠ eslint-plugin-react(button-has-type): `button` elements must have a valid `type` attribute.
╭─[button_has_type.tsx:1:9]
@@ -104,7 +104,7 @@ source: crates/oxc_linter/src/tester.rs
1 │
· ─────────────────────────────────────
╰────
- help: Change the `type` attribute to one of the allowed values: `button`, `submit`, or `reset`.
+ help: Change the `type` attribute to one of the allowed values: `button` or `submit`.
⚠ eslint-plugin-react(button-has-type): `button` elements must have an explicit `type` attribute.
╭─[button_has_type.tsx:1:1]
@@ -139,7 +139,7 @@ source: crates/oxc_linter/src/tester.rs
1 │ React.createElement("button", {type: "reset"})
· ─────────────
╰────
- help: Change the `type` attribute to one of the allowed values: `button`, `submit`, or `reset`.
+ help: Change the `type` attribute to one of the allowed values: `button` or `submit`.
⚠ eslint-plugin-react(button-has-type): `button` elements must have a valid `type` attribute.
╭─[button_has_type.tsx:1:32]
@@ -160,7 +160,7 @@ source: crates/oxc_linter/src/tester.rs
1 │ React.createElement("button", {type: condition ? "button" : "reset"})
· ────────────────────────────────────
╰────
- help: Change the `type` attribute to one of the allowed values: `button`, `submit`, or `reset`.
+ help: Change the `type` attribute to one of the allowed values: `button` or `submit`.
⚠ eslint-plugin-react(button-has-type): `button` elements must have a valid `type` attribute.
╭─[button_has_type.tsx:1:32]
@@ -181,7 +181,14 @@ source: crates/oxc_linter/src/tester.rs
1 │ React.createElement("button", {type: condition ? "reset" : "button"})
· ────────────────────────────────────
╰────
- help: Change the `type` attribute to one of the allowed values: `button`, `submit`, or `reset`.
+ help: Change the `type` attribute to one of the allowed values: `button` or `submit`.
+
+ ⚠ eslint-plugin-react(button-has-type): `button` elements must have a valid `type` attribute.
+ ╭─[button_has_type.tsx:1:32]
+ 1 │ React.createElement("button", {type: condition ? "reset" : "button"})
+ · ────────────────────────────────────
+ ╰────
+ help: Change the `type` attribute to one of the allowed values: `button`.
⚠ eslint-plugin-react(button-has-type): `button` elements must have an explicit `type` attribute.
╭─[button_has_type.tsx:1:1]