From c18619ee4c47f91316d8f62f86b2b2abdd499d06 Mon Sep 17 00:00:00 2001 From: Yuji Sugiura <6259812+leaysgur@users.noreply.github.com> Date: Thu, 25 Jan 2024 17:54:52 +0900 Subject: [PATCH] fix(linter): use correct rule name (#2169) Found by accident but it should be. - [x] react/jsx-no-comment-text-nodes - `jsx-no-comment-textnodes` is correct - https://github.com/jsx-eslint/eslint-plugin-react/blob/master/lib/rules/jsx-no-comment-textnodes.js - [x] react/no-dangerously-set-inner-html - `no-danger` is correct - https://github.com/jsx-eslint/eslint-plugin-react/blob/master/lib/rules/no-danger.js - [x] react-perf/no-jsx-as-prop - Correct name has `jsx-` prefix - https://github.com/cvazac/eslint-plugin-react-perf/tree/master/lib/rules - [x] react-perf/no-new-array-as-prop - The same as above - [x] react-perf/no-new-function-as-props - The same as above - [x] react-perf/no-new-object-as-prop - The same as above - [x] jsx-a11y/tab-index-no-positive - `tabindex-no-positive` is correct - https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/src/rules/tabindex-no-positive.js - [x] jsx-a11y/role-support-aria-props - `role-suports-aria-props` is correct - https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/src/rules/role-supports-aria-props.js - - - +1, - typescript/consistent-type-exports - Listed in `disable-type-checked` config == This is type checking rule but implemented - https://github.com/typescript-eslint/typescript-eslint/blob/8622286207b3e04ddd260eaa8ac71927d47edd7d/packages/eslint-plugin/src/configs/disable-type-checked.ts#L12 - Should remove it..? --- crates/oxc_linter/src/rules.rs | 32 +-- ...a_props.rs => role_supports_aria_props.rs} | 18 +- ...no_positive.rs => tabindex_no_positive.rs} | 14 +- ...t_nodes.rs => jsx_no_comment_textnodes.rs} | 14 +- ...erously_set_inner_html.rs => no_danger.rs} | 16 +- ...o_jsx_as_prop.rs => jsx_no_jsx_as_prop.rs} | 14 +- ...as_prop.rs => jsx_no_new_array_as_prop.rs} | 14 +- ...ops.rs => jsx_no_new_function_as_props.rs} | 14 +- ...s_prop.rs => jsx_no_new_object_as_prop.rs} | 14 +- .../snapshots/jsx_no_comment_textnodes.snap | 66 +++++ .../src/snapshots/jsx_no_jsx_as_prop.snap | 33 +++ .../snapshots/jsx_no_new_array_as_prop.snap | 47 ++++ .../jsx_no_new_function_as_props.snap | 68 +++++ .../snapshots/jsx_no_new_object_as_prop.snap | 54 ++++ .../oxc_linter/src/snapshots/no_danger.snap | 33 +++ .../snapshots/role_supports_aria_props.snap | 257 ++++++++++++++++++ .../src/snapshots/tabindex_no_positive.snap | 40 +++ 17 files changed, 672 insertions(+), 76 deletions(-) rename crates/oxc_linter/src/rules/jsx_a11y/{role_support_aria_props.rs => role_supports_aria_props.rs} (98%) rename crates/oxc_linter/src/rules/jsx_a11y/{tab_index_no_positive.rs => tabindex_no_positive.rs} (88%) rename crates/oxc_linter/src/rules/react/{jsx_no_comment_text_nodes.rs => jsx_no_comment_textnodes.rs} (94%) rename crates/oxc_linter/src/rules/react/{no_dangerously_set_inner_html.rs => no_danger.rs} (84%) rename crates/oxc_linter/src/rules/react_perf/{no_jsx_as_prop.rs => jsx_no_jsx_as_prop.rs} (87%) rename crates/oxc_linter/src/rules/react_perf/{no_new_array_as_prop.rs => jsx_no_new_array_as_prop.rs} (88%) rename crates/oxc_linter/src/rules/react_perf/{no_new_function_as_props.rs => jsx_no_new_function_as_props.rs} (90%) rename crates/oxc_linter/src/rules/react_perf/{no_new_object_as_prop.rs => jsx_no_new_object_as_prop.rs} (88%) create mode 100644 crates/oxc_linter/src/snapshots/jsx_no_comment_textnodes.snap create mode 100644 crates/oxc_linter/src/snapshots/jsx_no_jsx_as_prop.snap create mode 100644 crates/oxc_linter/src/snapshots/jsx_no_new_array_as_prop.snap create mode 100644 crates/oxc_linter/src/snapshots/jsx_no_new_function_as_props.snap create mode 100644 crates/oxc_linter/src/snapshots/jsx_no_new_object_as_prop.snap create mode 100644 crates/oxc_linter/src/snapshots/no_danger.snap create mode 100644 crates/oxc_linter/src/snapshots/role_supports_aria_props.snap create mode 100644 crates/oxc_linter/src/snapshots/tabindex_no_positive.snap diff --git a/crates/oxc_linter/src/rules.rs b/crates/oxc_linter/src/rules.rs index 26ddd11536d29..c8f4941a8f221 100644 --- a/crates/oxc_linter/src/rules.rs +++ b/crates/oxc_linter/src/rules.rs @@ -149,13 +149,13 @@ mod jest { mod react { pub mod button_has_type; pub mod jsx_key; - pub mod jsx_no_comment_text_nodes; + pub mod jsx_no_comment_textnodes; pub mod jsx_no_duplicate_props; pub mod jsx_no_target_blank; pub mod jsx_no_undef; pub mod jsx_no_useless_fragment; pub mod no_children_prop; - pub mod no_dangerously_set_inner_html; + pub mod no_danger; pub mod no_direct_mutation_state; pub mod no_find_dom_node; pub mod no_is_mounted; @@ -168,10 +168,10 @@ mod react { } mod react_perf { - pub mod no_jsx_as_prop; - pub mod no_new_array_as_prop; - pub mod no_new_function_as_props; - pub mod no_new_object_as_prop; + pub mod jsx_no_jsx_as_prop; + pub mod jsx_no_new_array_as_prop; + pub mod jsx_no_new_function_as_props; + pub mod jsx_no_new_object_as_prop; } mod unicorn { @@ -277,9 +277,9 @@ mod jsx_a11y { pub mod no_redundant_roles; pub mod prefer_tag_over_role; pub mod role_has_required_aria_props; - pub mod role_support_aria_props; + pub mod role_supports_aria_props; pub mod scope; - pub mod tab_index_no_positive; + pub mod tabindex_no_positive; } mod oxc { @@ -507,13 +507,13 @@ oxc_macros::declare_all_lint_rules! { react::button_has_type, react::jsx_no_target_blank, react::jsx_key, - react::jsx_no_comment_text_nodes, + react::jsx_no_comment_textnodes, react::jsx_no_duplicate_props, react::jsx_no_useless_fragment, react::jsx_no_undef, react::react_in_jsx_scope, react::no_children_prop, - react::no_dangerously_set_inner_html, + react::no_danger, react::no_direct_mutation_state, react::no_find_dom_node, react::no_render_return_value, @@ -522,10 +522,10 @@ oxc_macros::declare_all_lint_rules! { react::no_is_mounted, react::no_unknown_property, react::require_render_return, - react_perf::no_jsx_as_prop, - react_perf::no_new_array_as_prop, - react_perf::no_new_function_as_props, - react_perf::no_new_object_as_prop, + react_perf::jsx_no_jsx_as_prop, + react_perf::jsx_no_new_array_as_prop, + react_perf::jsx_no_new_function_as_props, + react_perf::jsx_no_new_object_as_prop, import::default, import::no_named_as_default_member, import::no_named_as_default, @@ -555,10 +555,10 @@ oxc_macros::declare_all_lint_rules! { jsx_a11y::prefer_tag_over_role, jsx_a11y::role_has_required_aria_props, jsx_a11y::scope, - jsx_a11y::tab_index_no_positive, + jsx_a11y::tabindex_no_positive, jsx_a11y::aria_role, jsx_a11y::no_distracting_elements, - jsx_a11y::role_support_aria_props, + jsx_a11y::role_supports_aria_props, jsx_a11y::autocomplete_valid, oxc::approx_constant, oxc::const_comparisons, diff --git a/crates/oxc_linter/src/rules/jsx_a11y/role_support_aria_props.rs b/crates/oxc_linter/src/rules/jsx_a11y/role_supports_aria_props.rs similarity index 98% rename from crates/oxc_linter/src/rules/jsx_a11y/role_support_aria_props.rs rename to crates/oxc_linter/src/rules/jsx_a11y/role_supports_aria_props.rs index b0d0ea45f1432..6780a01b33a50 100644 --- a/crates/oxc_linter/src/rules/jsx_a11y/role_support_aria_props.rs +++ b/crates/oxc_linter/src/rules/jsx_a11y/role_supports_aria_props.rs @@ -43,25 +43,25 @@ declare_oxc_lint!( /// /// ``` /// - RoleSupportAriaProps, + RoleSupportsAriaProps, correctness ); #[derive(Debug, Default, Clone)] -pub struct RoleSupportAriaProps; +pub struct RoleSupportsAriaProps; #[derive(Debug, Error, Diagnostic)] -enum RoleSupportAriaPropsDiagnostic { - #[error("eslint-plugin-jsx-a11y(role-support-aria-props): The attribute {1} is not supported by the role {2}.")] +enum RoleSupportsAriaPropsDiagnostic { + #[error("eslint-plugin-jsx-a11y(role-supports-aria-props): The attribute {1} is not supported by the role {2}.")] #[diagnostic(severity(warning), help("Try to remove invalid attribute {1}."))] Default(#[label] Span, String, String), - #[error("eslint-plugin-jsx-a11y(role-support-aria-props): The attribute {1} is not supported by the role {2}. This role is implicit on the element {3}.")] + #[error("eslint-plugin-jsx-a11y(role-supports-aria-props): The attribute {1} is not supported by the role {2}. This role is implicit on the element {3}.")] #[diagnostic(severity(warning), help("Try to remove invalid attribute {1}."))] IsImplicit(#[label] Span, String, String, String), } -impl Rule for RoleSupportAriaProps { +impl Rule for RoleSupportsAriaProps { fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { if let AstKind::JSXOpeningElement(jsx_el) = node.kind() { if let Some(el_type) = get_element_type(ctx, jsx_el) { @@ -81,14 +81,14 @@ impl Rule for RoleSupportAriaProps { let name = get_jsx_attribute_name(&attr.name).to_lowercase(); if invalid_props.contains(&&name.as_str()) { ctx.diagnostic(if is_implicit { - RoleSupportAriaPropsDiagnostic::IsImplicit( + RoleSupportsAriaPropsDiagnostic::IsImplicit( attr.span, name, role_value.to_string(), el_type.clone(), ) } else { - RoleSupportAriaPropsDiagnostic::Default( + RoleSupportsAriaPropsDiagnostic::Default( attr.span, name, role_value.to_string(), @@ -1597,5 +1597,5 @@ fn test() { (r#""#, None, Some(settings()), None), ]; - Tester::new(RoleSupportAriaProps::NAME, pass, fail).test_and_snapshot(); + Tester::new(RoleSupportsAriaProps::NAME, pass, fail).test_and_snapshot(); } diff --git a/crates/oxc_linter/src/rules/jsx_a11y/tab_index_no_positive.rs b/crates/oxc_linter/src/rules/jsx_a11y/tabindex_no_positive.rs similarity index 88% rename from crates/oxc_linter/src/rules/jsx_a11y/tab_index_no_positive.rs rename to crates/oxc_linter/src/rules/jsx_a11y/tabindex_no_positive.rs index e90ce6d6fdbaf..ff6eca72f30d7 100644 --- a/crates/oxc_linter/src/rules/jsx_a11y/tab_index_no_positive.rs +++ b/crates/oxc_linter/src/rules/jsx_a11y/tabindex_no_positive.rs @@ -15,13 +15,13 @@ use crate::{ #[derive(Debug, Error, Diagnostic)] #[error( - "eslint-plugin-jsx-a11y(tab-index-no-positive): Avoid positive integer values for tabIndex." + "eslint-plugin-jsx-a11y(tabindex-no-positive): Avoid positive integer values for tabIndex." )] #[diagnostic(severity(warning), help("Change the tabIndex prop to a non-negative value"))] -struct TabIndexNoPositiveDiagnostic(#[label] pub Span); +struct TabindexNoPositiveDiagnostic(#[label] pub Span); #[derive(Debug, Default, Clone)] -pub struct TabIndexNoPositive; +pub struct TabindexNoPositive; declare_oxc_lint!( /// ### What it does @@ -39,11 +39,11 @@ declare_oxc_lint!( /// foo /// bar /// ``` - TabIndexNoPositive, + TabindexNoPositive, correctness ); -impl Rule for TabIndexNoPositive { +impl Rule for TabindexNoPositive { fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { let AstKind::JSXOpeningElement(jsx_el) = node.kind() else { return }; if let Some(tab_index_prop) = has_jsx_prop_lowercase(jsx_el, "tabIndex") { @@ -57,7 +57,7 @@ fn check_and_diagnose(attr: &JSXAttributeItem, ctx: &LintContext<'_>) { JSXAttributeItem::Attribute(attr) => attr.value.as_ref().map_or((), |value| { if let Ok(parsed_value) = parse_jsx_value(value) { if parsed_value > 0.0 { - ctx.diagnostic(TabIndexNoPositiveDiagnostic(attr.span)); + ctx.diagnostic(TabindexNoPositiveDiagnostic(attr.span)); } } }), @@ -98,5 +98,5 @@ fn test() { (r"
", None), ]; - Tester::new(TabIndexNoPositive::NAME, pass, fail).test_and_snapshot(); + Tester::new(TabindexNoPositive::NAME, pass, fail).test_and_snapshot(); } diff --git a/crates/oxc_linter/src/rules/react/jsx_no_comment_text_nodes.rs b/crates/oxc_linter/src/rules/react/jsx_no_comment_textnodes.rs similarity index 94% rename from crates/oxc_linter/src/rules/react/jsx_no_comment_text_nodes.rs rename to crates/oxc_linter/src/rules/react/jsx_no_comment_textnodes.rs index 7118272018876..11b1be45a3481 100644 --- a/crates/oxc_linter/src/rules/react/jsx_no_comment_text_nodes.rs +++ b/crates/oxc_linter/src/rules/react/jsx_no_comment_textnodes.rs @@ -11,12 +11,12 @@ use regex::Regex; use crate::{context::LintContext, rule::Rule, AstNode}; #[derive(Debug, Error, Diagnostic)] -#[error("eslint-plugin-react(jsx-no-comment-TextNodes): Comments inside children section of tag should be placed inside braces")] +#[error("eslint-plugin-react(jsx-no-comment-textnodes): Comments inside children section of tag should be placed inside braces")] #[diagnostic(severity(warning))] -struct JsxNoCommentTextNodesDiagnostic(#[label] pub Span); +struct JsxNoCommentTextnodesDiagnostic(#[label] pub Span); #[derive(Debug, Default, Clone)] -pub struct JsxNoCommentTextNodes; +pub struct JsxNoCommentTextnodes; declare_oxc_lint!( /// ### What it does @@ -49,16 +49,16 @@ declare_oxc_lint!( /// return
{/* empty div */}
; /// } /// ``` - JsxNoCommentTextNodes, + JsxNoCommentTextnodes, suspicious ); -impl Rule for JsxNoCommentTextNodes { +impl Rule for JsxNoCommentTextnodes { fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { let AstKind::JSXText(jsx_text) = node.kind() else { return }; if control_patterns(&jsx_text.value) { - ctx.diagnostic(JsxNoCommentTextNodesDiagnostic(jsx_text.span)); + ctx.diagnostic(JsxNoCommentTextnodesDiagnostic(jsx_text.span)); } } } @@ -309,5 +309,5 @@ fn test() { ), ]; - Tester::new(JsxNoCommentTextNodes::NAME, pass, fail).test_and_snapshot(); + Tester::new(JsxNoCommentTextnodes::NAME, pass, fail).test_and_snapshot(); } diff --git a/crates/oxc_linter/src/rules/react/no_dangerously_set_inner_html.rs b/crates/oxc_linter/src/rules/react/no_danger.rs similarity index 84% rename from crates/oxc_linter/src/rules/react/no_dangerously_set_inner_html.rs rename to crates/oxc_linter/src/rules/react/no_danger.rs index 635cded40ac94..d7564deb2de2d 100644 --- a/crates/oxc_linter/src/rules/react/no_dangerously_set_inner_html.rs +++ b/crates/oxc_linter/src/rules/react/no_danger.rs @@ -20,10 +20,10 @@ use crate::{ #[derive(Debug, Error, Diagnostic)] #[error("eslint-plugin-react(no-danger): Do not use `dangerouslySetInnerHTML` prop")] #[diagnostic(severity(warning), help("`dangerouslySetInnerHTML` is a way to inject HTML into your React component. This is dangerous because it can easily lead to XSS vulnerabilities."))] -struct NoDangerouslySetInnerHtmlDiagnostic(#[label] pub Span); +struct NoDangerDiagnostic(#[label] pub Span); #[derive(Debug, Default, Clone)] -pub struct NoDangerouslySetInnerHtml; +pub struct NoDanger; declare_oxc_lint!( /// ### What it does @@ -37,18 +37,18 @@ declare_oxc_lint!( /// ### Example /// ```javascript /// ``` - NoDangerouslySetInnerHtml, + NoDanger, restriction ); -impl Rule for NoDangerouslySetInnerHtml { +impl Rule for NoDanger { fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { match node.kind() { AstKind::JSXElement(jsx_elem) => { if let Some(JSXAttributeItem::Attribute(prop)) = has_jsx_prop(&jsx_elem.opening_element, "dangerouslySetInnerHTML") { - ctx.diagnostic(NoDangerouslySetInnerHtmlDiagnostic(prop.name.span())); + ctx.diagnostic(NoDangerDiagnostic(prop.name.span())); } } AstKind::CallExpression(call_expr) => { @@ -64,9 +64,7 @@ impl Rule for NoDangerouslySetInnerHtml { if let ObjectPropertyKind::ObjectProperty(obj_prop) = prop { if let Some(prop_name) = obj_prop.key.static_name() { if prop_name.as_str() == "dangerouslySetInnerHTML" { - ctx.diagnostic(NoDangerouslySetInnerHtmlDiagnostic( - obj_prop.key.span(), - )); + ctx.diagnostic(NoDangerDiagnostic(obj_prop.key.span())); } } } @@ -94,5 +92,5 @@ fn test() { ("React.createElement(\"button\", { dangerouslySetInnerHTML: { __html: \"baz\" } }, \"Foo\");", None), ]; - Tester::new(NoDangerouslySetInnerHtml::NAME, pass, fail).test_and_snapshot(); + Tester::new(NoDanger::NAME, pass, fail).test_and_snapshot(); } diff --git a/crates/oxc_linter/src/rules/react_perf/no_jsx_as_prop.rs b/crates/oxc_linter/src/rules/react_perf/jsx_no_jsx_as_prop.rs similarity index 87% rename from crates/oxc_linter/src/rules/react_perf/no_jsx_as_prop.rs rename to crates/oxc_linter/src/rules/react_perf/jsx_no_jsx_as_prop.rs index 8eacf4857aca3..d6c8a72c473b2 100644 --- a/crates/oxc_linter/src/rules/react_perf/no_jsx_as_prop.rs +++ b/crates/oxc_linter/src/rules/react_perf/jsx_no_jsx_as_prop.rs @@ -13,13 +13,13 @@ use crate::{context::LintContext, rule::Rule, utils::get_prop_value, AstNode}; #[derive(Debug, Error, Diagnostic)] #[error( - "eslint-plugin-react-perf(no-jsx-as-prop): JSX attribute values should not contain other JSX." + "eslint-plugin-react-perf(jsx-no-jsx-as-prop): JSX attribute values should not contain other JSX." )] #[diagnostic(severity(warning), help(r"simplify props or memoize props in the parent component (https://react.dev/reference/react/memo#my-component-rerenders-when-a-prop-is-an-object-or-array)."))] -struct NoJsxAsPropDiagnostic(#[label] pub Span); +struct JsxNoJsxAsPropDiagnostic(#[label] pub Span); #[derive(Debug, Default, Clone)] -pub struct NoJsxAsProp; +pub struct JsxNoJsxAsProp; declare_oxc_lint!( /// ### What it does @@ -36,11 +36,11 @@ declare_oxc_lint!( /// // Good /// /// ``` - NoJsxAsProp, + JsxNoJsxAsProp, correctness ); -impl Rule for NoJsxAsProp { +impl Rule for JsxNoJsxAsProp { fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { if let AstKind::JSXElement(jsx_elem) = node.kind() { check_jsx_element(jsx_elem, ctx); @@ -57,7 +57,7 @@ fn check_jsx_element<'a>(jsx_elem: &JSXElement<'a>, ctx: &LintContext<'a>) { .. })) => { if let Some(span) = check_expression(expr) { - ctx.diagnostic(NoJsxAsPropDiagnostic(span)); + ctx.diagnostic(JsxNoJsxAsPropDiagnostic(span)); } } _ => {} @@ -91,5 +91,5 @@ fn test() { r")} />", ]; - Tester::new(NoJsxAsProp::NAME, pass, fail).with_react_perf_plugin(true).test_and_snapshot(); + Tester::new(JsxNoJsxAsProp::NAME, pass, fail).with_react_perf_plugin(true).test_and_snapshot(); } diff --git a/crates/oxc_linter/src/rules/react_perf/no_new_array_as_prop.rs b/crates/oxc_linter/src/rules/react_perf/jsx_no_new_array_as_prop.rs similarity index 88% rename from crates/oxc_linter/src/rules/react_perf/no_new_array_as_prop.rs rename to crates/oxc_linter/src/rules/react_perf/jsx_no_new_array_as_prop.rs index eeb4b62d7a3ef..39b8ec800f6d4 100644 --- a/crates/oxc_linter/src/rules/react_perf/no_new_array_as_prop.rs +++ b/crates/oxc_linter/src/rules/react_perf/jsx_no_new_array_as_prop.rs @@ -17,12 +17,12 @@ use crate::{ }; #[derive(Debug, Error, Diagnostic)] -#[error("eslint-plugin-react-perf(no-new-array-as-prop): JSX attribute values should not contain Arrays created in the same scope.")] +#[error("eslint-plugin-react-perf(jsx-no-new-array-as-prop): JSX attribute values should not contain Arrays created in the same scope.")] #[diagnostic(severity(warning), help(r"simplify props or memoize props in the parent component (https://react.dev/reference/react/memo#my-component-rerenders-when-a-prop-is-an-object-or-array)."))] -struct NoNewArrayAsPropDiagnostic(#[label] pub Span); +struct JsxNoNewArrayAsPropDiagnostic(#[label] pub Span); #[derive(Debug, Default, Clone)] -pub struct NoNewArrayAsProp; +pub struct JsxNoNewArrayAsProp; declare_oxc_lint!( /// ### What it does @@ -42,11 +42,11 @@ declare_oxc_lint!( /// // Good /// /// ``` - NoNewArrayAsProp, + JsxNoNewArrayAsProp, correctness ); -impl Rule for NoNewArrayAsProp { +impl Rule for JsxNoNewArrayAsProp { fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { if let AstKind::JSXElement(jsx_elem) = node.kind() { check_jsx_element(jsx_elem, ctx); @@ -63,7 +63,7 @@ fn check_jsx_element<'a>(jsx_elem: &JSXElement<'a>, ctx: &LintContext<'a>) { .. })) => { if let Some(span) = check_expression(expr) { - ctx.diagnostic(NoNewArrayAsPropDiagnostic(span)); + ctx.diagnostic(JsxNoNewArrayAsPropDiagnostic(span)); } } _ => {} @@ -113,7 +113,7 @@ fn test() { r"", ]; - Tester::new(NoNewArrayAsProp::NAME, pass, fail) + Tester::new(JsxNoNewArrayAsProp::NAME, pass, fail) .with_react_perf_plugin(true) .test_and_snapshot(); } diff --git a/crates/oxc_linter/src/rules/react_perf/no_new_function_as_props.rs b/crates/oxc_linter/src/rules/react_perf/jsx_no_new_function_as_props.rs similarity index 90% rename from crates/oxc_linter/src/rules/react_perf/no_new_function_as_props.rs rename to crates/oxc_linter/src/rules/react_perf/jsx_no_new_function_as_props.rs index 81ca51ab3f5fd..ebc1ef38c088d 100644 --- a/crates/oxc_linter/src/rules/react_perf/no_new_function_as_props.rs +++ b/crates/oxc_linter/src/rules/react_perf/jsx_no_new_function_as_props.rs @@ -20,12 +20,12 @@ use crate::{ }; #[derive(Debug, Error, Diagnostic)] -#[error("eslint-plugin-react-perf(no-new-function-as-props): JSX attribute values should not contain functions created in the same scope.")] +#[error("eslint-plugin-react-perf(jsx-no-new-function-as-props): JSX attribute values should not contain functions created in the same scope.")] #[diagnostic(severity(warning), help(r"simplify props or memoize props in the parent component (https://react.dev/reference/react/memo#my-component-rerenders-when-a-prop-is-an-object-or-array)."))] -struct NoNewFunctionAsPropsDiagnostic(#[label] pub Span); +struct JsxNoNewFunctionAsPropsDiagnostic(#[label] pub Span); #[derive(Debug, Default, Clone)] -pub struct NoNewFunctionAsProps; +pub struct JsxNoNewFunctionAsProps; declare_oxc_lint!( /// ### What it does @@ -40,11 +40,11 @@ declare_oxc_lint!( /// // Good /// /// ``` - NoNewFunctionAsProps, + JsxNoNewFunctionAsProps, correctness ); -impl Rule for NoNewFunctionAsProps { +impl Rule for JsxNoNewFunctionAsProps { fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { if let AstKind::JSXElement(jsx_elem) = node.kind() { check_jsx_element(jsx_elem, ctx); @@ -61,7 +61,7 @@ fn check_jsx_element<'a>(jsx_elem: &JSXElement<'a>, ctx: &LintContext<'a>) { .. })) => { if let Some(span) = check_expression(expr) { - ctx.diagnostic(NoNewFunctionAsPropsDiagnostic(span)); + ctx.diagnostic(JsxNoNewFunctionAsPropsDiagnostic(span)); } } _ => {} @@ -139,7 +139,7 @@ fn test() { r"", ]; - Tester::new(NoNewFunctionAsProps::NAME, pass, fail) + Tester::new(JsxNoNewFunctionAsProps::NAME, pass, fail) .with_react_perf_plugin(true) .test_and_snapshot(); } diff --git a/crates/oxc_linter/src/rules/react_perf/no_new_object_as_prop.rs b/crates/oxc_linter/src/rules/react_perf/jsx_no_new_object_as_prop.rs similarity index 88% rename from crates/oxc_linter/src/rules/react_perf/no_new_object_as_prop.rs rename to crates/oxc_linter/src/rules/react_perf/jsx_no_new_object_as_prop.rs index aca76b00107e6..376562a05ccf3 100644 --- a/crates/oxc_linter/src/rules/react_perf/no_new_object_as_prop.rs +++ b/crates/oxc_linter/src/rules/react_perf/jsx_no_new_object_as_prop.rs @@ -17,12 +17,12 @@ use crate::{ }; #[derive(Debug, Error, Diagnostic)] -#[error("eslint-plugin-react-perf(no-new-object-as-prop): JSX attribute values should not contain objects created in the same scope.")] +#[error("eslint-plugin-react-perf(jsx-no-new-object-as-prop): JSX attribute values should not contain objects created in the same scope.")] #[diagnostic(severity(warning), help(r"simplify props or memoize props in the parent component (https://react.dev/reference/react/memo#my-component-rerenders-when-a-prop-is-an-object-or-array)."))] -struct NoNewObjectAsPropDiagnostic(#[label] pub Span); +struct JsxNoNewObjectAsPropDiagnostic(#[label] pub Span); #[derive(Debug, Default, Clone)] -pub struct NoNewObjectAsProp; +pub struct JsxNoNewObjectAsProp; declare_oxc_lint!( /// ### What it does @@ -41,11 +41,11 @@ declare_oxc_lint!( /// // Good /// /// ``` - NoNewObjectAsProp, + JsxNoNewObjectAsProp, correctness ); -impl Rule for NoNewObjectAsProp { +impl Rule for JsxNoNewObjectAsProp { fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { if let AstKind::JSXElement(jsx_elem) = node.kind() { check_jsx_element(jsx_elem, ctx); @@ -62,7 +62,7 @@ fn check_jsx_element<'a>(jsx_elem: &JSXElement<'a>, ctx: &LintContext<'a>) { .. })) => { if let Some(span) = check_expression(expr) { - ctx.diagnostic(NoNewObjectAsPropDiagnostic(span)); + ctx.diagnostic(JsxNoNewObjectAsPropDiagnostic(span)); } } _ => {} @@ -113,7 +113,7 @@ fn test() { r"", ]; - Tester::new(NoNewObjectAsProp::NAME, pass, fail) + Tester::new(JsxNoNewObjectAsProp::NAME, pass, fail) .with_react_perf_plugin(true) .test_and_snapshot(); } diff --git a/crates/oxc_linter/src/snapshots/jsx_no_comment_textnodes.snap b/crates/oxc_linter/src/snapshots/jsx_no_comment_textnodes.snap new file mode 100644 index 0000000000000..fb7a78b17a1a2 --- /dev/null +++ b/crates/oxc_linter/src/snapshots/jsx_no_comment_textnodes.snap @@ -0,0 +1,66 @@ +--- +source: crates/oxc_linter/src/tester.rs +expression: jsx_no_comment_textnodes +--- + ⚠ eslint-plugin-react(jsx-no-comment-textnodes): Comments inside children section of tag should be placed inside braces + ╭─[jsx_no_comment_textnodes.tsx:3:1] + 3 │ render() { + 4 │ return (
// invalid
); + · ────────── + 5 │ } + ╰──── + + ⚠ eslint-plugin-react(jsx-no-comment-textnodes): Comments inside children section of tag should be placed inside braces + ╭─[jsx_no_comment_textnodes.tsx:3:1] + 3 │ render() { + 4 │ return (<>// invalid); + · ────────── + 5 │ } + ╰──── + + ⚠ eslint-plugin-react(jsx-no-comment-textnodes): Comments inside children section of tag should be placed inside braces + ╭─[jsx_no_comment_textnodes.tsx:3:1] + 3 │ render() { + 4 │ return (
/* invalid */
); + · ───────────── + 5 │ } + ╰──── + + ⚠ eslint-plugin-react(jsx-no-comment-textnodes): Comments inside children section of tag should be placed inside braces + ╭─[jsx_no_comment_textnodes.tsx:4:1] + 4 │ return ( + 5 │ ╭─▶
+ 6 │ │ // invalid + 7 │ ╰─▶
+ 8 │ ); + ╰──── + + ⚠ eslint-plugin-react(jsx-no-comment-textnodes): Comments inside children section of tag should be placed inside braces + ╭─[jsx_no_comment_textnodes.tsx:4:1] + 4 │ return ( + 5 │ ╭─▶
+ 6 │ │ asdjfl + 7 │ │ /* invalid */ + 8 │ │ foo + 9 │ ╰─▶
+ 10 │ ); + ╰──── + + ⚠ eslint-plugin-react(jsx-no-comment-textnodes): Comments inside children section of tag should be placed inside braces + ╭─[jsx_no_comment_textnodes.tsx:5:1] + 5 │
+ 6 │ ╭─▶ {'asdjfl'} + 7 │ │ // invalid + 8 │ ╰─▶ {'foo'} + 9 │
+ ╰──── + + ⚠ eslint-plugin-react(jsx-no-comment-textnodes): Comments inside children section of tag should be placed inside braces + ╭─[jsx_no_comment_textnodes.tsx:2:1] + 2 │ const Component2 = () => { + 3 │ return /*; + · ── + 4 │ }; + ╰──── + + diff --git a/crates/oxc_linter/src/snapshots/jsx_no_jsx_as_prop.snap b/crates/oxc_linter/src/snapshots/jsx_no_jsx_as_prop.snap new file mode 100644 index 0000000000000..e0d25fc6f958f --- /dev/null +++ b/crates/oxc_linter/src/snapshots/jsx_no_jsx_as_prop.snap @@ -0,0 +1,33 @@ +--- +source: crates/oxc_linter/src/tester.rs +expression: jsx_no_jsx_as_prop +--- + ⚠ eslint-plugin-react-perf(jsx-no-jsx-as-prop): JSX attribute values should not contain other JSX. + ╭─[jsx_no_jsx_as_prop.tsx:1:1] + 1 │ } /> + · ─────────── + ╰──── + help: simplify props or memoize props in the parent component (https://react.dev/reference/react/memo#my-component-rerenders-when-a-prop-is-an-object-or-array). + + ⚠ eslint-plugin-react-perf(jsx-no-jsx-as-prop): JSX attribute values should not contain other JSX. + ╭─[jsx_no_jsx_as_prop.tsx:1:1] + 1 │ } /> + · ─────────── + ╰──── + help: simplify props or memoize props in the parent component (https://react.dev/reference/react/memo#my-component-rerenders-when-a-prop-is-an-object-or-array). + + ⚠ eslint-plugin-react-perf(jsx-no-jsx-as-prop): JSX attribute values should not contain other JSX. + ╭─[jsx_no_jsx_as_prop.tsx:1:1] + 1 │ } /> + · ─────────── + ╰──── + help: simplify props or memoize props in the parent component (https://react.dev/reference/react/memo#my-component-rerenders-when-a-prop-is-an-object-or-array). + + ⚠ eslint-plugin-react-perf(jsx-no-jsx-as-prop): JSX attribute values should not contain other JSX. + ╭─[jsx_no_jsx_as_prop.tsx:1:1] + 1 │ )} /> + · ─────────── + ╰──── + help: simplify props or memoize props in the parent component (https://react.dev/reference/react/memo#my-component-rerenders-when-a-prop-is-an-object-or-array). + + diff --git a/crates/oxc_linter/src/snapshots/jsx_no_new_array_as_prop.snap b/crates/oxc_linter/src/snapshots/jsx_no_new_array_as_prop.snap new file mode 100644 index 0000000000000..fd9ce6daa1bfe --- /dev/null +++ b/crates/oxc_linter/src/snapshots/jsx_no_new_array_as_prop.snap @@ -0,0 +1,47 @@ +--- +source: crates/oxc_linter/src/tester.rs +expression: jsx_no_new_array_as_prop +--- + ⚠ eslint-plugin-react-perf(jsx-no-new-array-as-prop): JSX attribute values should not contain Arrays created in the same scope. + ╭─[jsx_no_new_array_as_prop.tsx:1:1] + 1 │ + · ── + ╰──── + help: simplify props or memoize props in the parent component (https://react.dev/reference/react/memo#my-component-rerenders-when-a-prop-is-an-object-or-array). + + ⚠ eslint-plugin-react-perf(jsx-no-new-array-as-prop): JSX attribute values should not contain Arrays created in the same scope. + ╭─[jsx_no_new_array_as_prop.tsx:1:1] + 1 │ + · ─────────── + ╰──── + help: simplify props or memoize props in the parent component (https://react.dev/reference/react/memo#my-component-rerenders-when-a-prop-is-an-object-or-array). + + ⚠ eslint-plugin-react-perf(jsx-no-new-array-as-prop): JSX attribute values should not contain Arrays created in the same scope. + ╭─[jsx_no_new_array_as_prop.tsx:1:1] + 1 │ + · ─────── + ╰──── + help: simplify props or memoize props in the parent component (https://react.dev/reference/react/memo#my-component-rerenders-when-a-prop-is-an-object-or-array). + + ⚠ eslint-plugin-react-perf(jsx-no-new-array-as-prop): JSX attribute values should not contain Arrays created in the same scope. + ╭─[jsx_no_new_array_as_prop.tsx:1:1] + 1 │ + · ── + ╰──── + help: simplify props or memoize props in the parent component (https://react.dev/reference/react/memo#my-component-rerenders-when-a-prop-is-an-object-or-array). + + ⚠ eslint-plugin-react-perf(jsx-no-new-array-as-prop): JSX attribute values should not contain Arrays created in the same scope. + ╭─[jsx_no_new_array_as_prop.tsx:1:1] + 1 │ + · ── + ╰──── + help: simplify props or memoize props in the parent component (https://react.dev/reference/react/memo#my-component-rerenders-when-a-prop-is-an-object-or-array). + + ⚠ eslint-plugin-react-perf(jsx-no-new-array-as-prop): JSX attribute values should not contain Arrays created in the same scope. + ╭─[jsx_no_new_array_as_prop.tsx:1:1] + 1 │ + · ── + ╰──── + help: simplify props or memoize props in the parent component (https://react.dev/reference/react/memo#my-component-rerenders-when-a-prop-is-an-object-or-array). + + diff --git a/crates/oxc_linter/src/snapshots/jsx_no_new_function_as_props.snap b/crates/oxc_linter/src/snapshots/jsx_no_new_function_as_props.snap new file mode 100644 index 0000000000000..def8e3913b2c3 --- /dev/null +++ b/crates/oxc_linter/src/snapshots/jsx_no_new_function_as_props.snap @@ -0,0 +1,68 @@ +--- +source: crates/oxc_linter/src/tester.rs +expression: jsx_no_new_function_as_props +--- + ⚠ eslint-plugin-react-perf(jsx-no-new-function-as-props): JSX attribute values should not contain functions created in the same scope. + ╭─[jsx_no_new_function_as_props.tsx:1:1] + 1 │ + · ─────────────────────── + ╰──── + help: simplify props or memoize props in the parent component (https://react.dev/reference/react/memo#my-component-rerenders-when-a-prop-is-an-object-or-array). + + ⚠ eslint-plugin-react-perf(jsx-no-new-function-as-props): JSX attribute values should not contain functions created in the same scope. + ╭─[jsx_no_new_function_as_props.tsx:1:1] + 1 │ true} /> + · ────────── + ╰──── + help: simplify props or memoize props in the parent component (https://react.dev/reference/react/memo#my-component-rerenders-when-a-prop-is-an-object-or-array). + + ⚠ eslint-plugin-react-perf(jsx-no-new-function-as-props): JSX attribute values should not contain functions created in the same scope. + ╭─[jsx_no_new_function_as_props.tsx:1:1] + 1 │ + · ───────────────────────────── + ╰──── + help: simplify props or memoize props in the parent component (https://react.dev/reference/react/memo#my-component-rerenders-when-a-prop-is-an-object-or-array). + + ⚠ eslint-plugin-react-perf(jsx-no-new-function-as-props): JSX attribute values should not contain functions created in the same scope. + ╭─[jsx_no_new_function_as_props.tsx:1:1] + 1 │ + · ────────── + ╰──── + help: simplify props or memoize props in the parent component (https://react.dev/reference/react/memo#my-component-rerenders-when-a-prop-is-an-object-or-array). + + ⚠ eslint-plugin-react-perf(jsx-no-new-function-as-props): JSX attribute values should not contain functions created in the same scope. + ╭─[jsx_no_new_function_as_props.tsx:1:1] + 1 │ + · ──────────────────────────── + ╰──── + help: simplify props or memoize props in the parent component (https://react.dev/reference/react/memo#my-component-rerenders-when-a-prop-is-an-object-or-array). + + ⚠ eslint-plugin-react-perf(jsx-no-new-function-as-props): JSX attribute values should not contain functions created in the same scope. + ╭─[jsx_no_new_function_as_props.tsx:1:1] + 1 │ + · ───────────── + ╰──── + help: simplify props or memoize props in the parent component (https://react.dev/reference/react/memo#my-component-rerenders-when-a-prop-is-an-object-or-array). + + ⚠ eslint-plugin-react-perf(jsx-no-new-function-as-props): JSX attribute values should not contain functions created in the same scope. + ╭─[jsx_no_new_function_as_props.tsx:1:1] + 1 │ + · ───────────── + ╰──── + help: simplify props or memoize props in the parent component (https://react.dev/reference/react/memo#my-component-rerenders-when-a-prop-is-an-object-or-array). + + ⚠ eslint-plugin-react-perf(jsx-no-new-function-as-props): JSX attribute values should not contain functions created in the same scope. + ╭─[jsx_no_new_function_as_props.tsx:1:1] + 1 │ + · ──────────── + ╰──── + help: simplify props or memoize props in the parent component (https://react.dev/reference/react/memo#my-component-rerenders-when-a-prop-is-an-object-or-array). + + ⚠ eslint-plugin-react-perf(jsx-no-new-function-as-props): JSX attribute values should not contain functions created in the same scope. + ╭─[jsx_no_new_function_as_props.tsx:1:1] + 1 │ + · ──────────── + ╰──── + help: simplify props or memoize props in the parent component (https://react.dev/reference/react/memo#my-component-rerenders-when-a-prop-is-an-object-or-array). + + diff --git a/crates/oxc_linter/src/snapshots/jsx_no_new_object_as_prop.snap b/crates/oxc_linter/src/snapshots/jsx_no_new_object_as_prop.snap new file mode 100644 index 0000000000000..e92c973a47788 --- /dev/null +++ b/crates/oxc_linter/src/snapshots/jsx_no_new_object_as_prop.snap @@ -0,0 +1,54 @@ +--- +source: crates/oxc_linter/src/tester.rs +expression: jsx_no_new_object_as_prop +--- + ⚠ eslint-plugin-react-perf(jsx-no-new-object-as-prop): JSX attribute values should not contain objects created in the same scope. + ╭─[jsx_no_new_object_as_prop.tsx:1:1] + 1 │ + · ── + ╰──── + help: simplify props or memoize props in the parent component (https://react.dev/reference/react/memo#my-component-rerenders-when-a-prop-is-an-object-or-array). + + ⚠ eslint-plugin-react-perf(jsx-no-new-object-as-prop): JSX attribute values should not contain objects created in the same scope. + ╭─[jsx_no_new_object_as_prop.tsx:1:1] + 1 │ + · ──────────── + ╰──── + help: simplify props or memoize props in the parent component (https://react.dev/reference/react/memo#my-component-rerenders-when-a-prop-is-an-object-or-array). + + ⚠ eslint-plugin-react-perf(jsx-no-new-object-as-prop): JSX attribute values should not contain objects created in the same scope. + ╭─[jsx_no_new_object_as_prop.tsx:1:1] + 1 │ + · ──────── + ╰──── + help: simplify props or memoize props in the parent component (https://react.dev/reference/react/memo#my-component-rerenders-when-a-prop-is-an-object-or-array). + + ⚠ eslint-plugin-react-perf(jsx-no-new-object-as-prop): JSX attribute values should not contain objects created in the same scope. + ╭─[jsx_no_new_object_as_prop.tsx:1:1] + 1 │
+ · ───────────────── + ╰──── + help: simplify props or memoize props in the parent component (https://react.dev/reference/react/memo#my-component-rerenders-when-a-prop-is-an-object-or-array). + + ⚠ eslint-plugin-react-perf(jsx-no-new-object-as-prop): JSX attribute values should not contain objects created in the same scope. + ╭─[jsx_no_new_object_as_prop.tsx:1:1] + 1 │ + · ── + ╰──── + help: simplify props or memoize props in the parent component (https://react.dev/reference/react/memo#my-component-rerenders-when-a-prop-is-an-object-or-array). + + ⚠ eslint-plugin-react-perf(jsx-no-new-object-as-prop): JSX attribute values should not contain objects created in the same scope. + ╭─[jsx_no_new_object_as_prop.tsx:1:1] + 1 │ + · ── + ╰──── + help: simplify props or memoize props in the parent component (https://react.dev/reference/react/memo#my-component-rerenders-when-a-prop-is-an-object-or-array). + + ⚠ eslint-plugin-react-perf(jsx-no-new-object-as-prop): JSX attribute values should not contain objects created in the same scope. + ╭─[jsx_no_new_object_as_prop.tsx:1:1] + 1 │ + · ── + ╰──── + help: simplify props or memoize props in the parent component (https://react.dev/reference/react/memo#my-component-rerenders-when-a-prop-is-an-object-or-array). + + diff --git a/crates/oxc_linter/src/snapshots/no_danger.snap b/crates/oxc_linter/src/snapshots/no_danger.snap new file mode 100644 index 0000000000000..976c564d64ed7 --- /dev/null +++ b/crates/oxc_linter/src/snapshots/no_danger.snap @@ -0,0 +1,33 @@ +--- +source: crates/oxc_linter/src/tester.rs +expression: no_danger +--- + ⚠ eslint-plugin-react(no-danger): Do not use `dangerouslySetInnerHTML` prop + ╭─[no_danger.tsx:1:1] + 1 │
; + · ─────────────────────── + ╰──── + help: `dangerouslySetInnerHTML` is a way to inject HTML into your React component. This is dangerous because it can easily lead to XSS vulnerabilities. + + ⚠ eslint-plugin-react(no-danger): Do not use `dangerouslySetInnerHTML` prop + ╭─[no_danger.tsx:1:1] + 1 │ ; + · ─────────────────────── + ╰──── + help: `dangerouslySetInnerHTML` is a way to inject HTML into your React component. This is dangerous because it can easily lead to XSS vulnerabilities. + + ⚠ eslint-plugin-react(no-danger): Do not use `dangerouslySetInnerHTML` prop + ╭─[no_danger.tsx:1:1] + 1 │ React.createElement("div", { dangerouslySetInnerHTML: { __html: "" } }); + · ─────────────────────── + ╰──── + help: `dangerouslySetInnerHTML` is a way to inject HTML into your React component. This is dangerous because it can easily lead to XSS vulnerabilities. + + ⚠ eslint-plugin-react(no-danger): Do not use `dangerouslySetInnerHTML` prop + ╭─[no_danger.tsx:1:1] + 1 │ React.createElement("button", { dangerouslySetInnerHTML: { __html: "baz" } }, "Foo"); + · ─────────────────────── + ╰──── + help: `dangerouslySetInnerHTML` is a way to inject HTML into your React component. This is dangerous because it can easily lead to XSS vulnerabilities. + + diff --git a/crates/oxc_linter/src/snapshots/role_supports_aria_props.snap b/crates/oxc_linter/src/snapshots/role_supports_aria_props.snap new file mode 100644 index 0000000000000..b98675642acda --- /dev/null +++ b/crates/oxc_linter/src/snapshots/role_supports_aria_props.snap @@ -0,0 +1,257 @@ +--- +source: crates/oxc_linter/src/tester.rs +expression: role_supports_aria_props +--- + ⚠ eslint-plugin-jsx-a11y(role-supports-aria-props): The attribute aria-checked is not supported by the role link. This role is implicit on the element a. + ╭─[role_supports_aria_props.tsx:1:1] + 1 │ + · ──────────── + ╰──── + help: Try to remove invalid attribute aria-checked. + + ⚠ eslint-plugin-jsx-a11y(role-supports-aria-props): The attribute aria-checked is not supported by the role link. This role is implicit on the element area. + ╭─[role_supports_aria_props.tsx:1:1] + 1 │ + · ──────────── + ╰──── + help: Try to remove invalid attribute aria-checked. + + ⚠ eslint-plugin-jsx-a11y(role-supports-aria-props): The attribute aria-checked is not supported by the role link. This role is implicit on the element link. + ╭─[role_supports_aria_props.tsx:1:1] + 1 │ + · ──────────── + ╰──── + help: Try to remove invalid attribute aria-checked. + + ⚠ eslint-plugin-jsx-a11y(role-supports-aria-props): The attribute aria-checked is not supported by the role img. This role is implicit on the element img. + ╭─[role_supports_aria_props.tsx:1:1] + 1 │ foobar + · ──────────── + ╰──── + help: Try to remove invalid attribute aria-checked. + + ⚠ eslint-plugin-jsx-a11y(role-supports-aria-props): The attribute aria-checked is not supported by the role toolbar. This role is implicit on the element menu. + ╭─[role_supports_aria_props.tsx:1:1] + 1 │ + · ──────────── + ╰──── + help: Try to remove invalid attribute aria-checked. + + ⚠ eslint-plugin-jsx-a11y(role-supports-aria-props): The attribute aria-checked is not supported by the role complementary. This role is implicit on the element aside. + ╭─[role_supports_aria_props.tsx:1:1] + 1 │