diff --git a/crates/oxc_linter/src/rules/react_perf/jsx_no_jsx_as_prop.rs b/crates/oxc_linter/src/rules/react_perf/jsx_no_jsx_as_prop.rs index 23210ceee3569..6eb43a7a4099b 100644 --- a/crates/oxc_linter/src/rules/react_perf/jsx_no_jsx_as_prop.rs +++ b/crates/oxc_linter/src/rules/react_perf/jsx_no_jsx_as_prop.rs @@ -38,6 +38,9 @@ declare_oxc_lint!( impl Rule for JsxNoJsxAsProp { fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { + if node.scope_id() == ctx.scopes().root_scope_id() { + return; + } if let AstKind::JSXElement(jsx_elem) = node.kind() { check_jsx_element(jsx_elem, ctx); } @@ -81,14 +84,21 @@ fn check_expression(expr: &Expression) -> Option { fn test() { use crate::tester::Tester; - let pass = vec![r""]; - - let fail = vec![ + let pass = vec![ + r"", + r"const Foo = () => ", r"} />", r"} />", r"} />", r")} />", ]; + let fail = vec![ + r"const Foo = () => (} />)", + r"const Foo = () => (} />)", + r"const Foo = () => (} />)", + r"const Foo = () => ()} />)", + ]; + Tester::new(JsxNoJsxAsProp::NAME, pass, fail).with_react_perf_plugin(true).test_and_snapshot(); } diff --git a/crates/oxc_linter/src/rules/react_perf/jsx_no_new_array_as_prop.rs b/crates/oxc_linter/src/rules/react_perf/jsx_no_new_array_as_prop.rs index 8aeaa914df844..bccfc9e9a8a6d 100644 --- a/crates/oxc_linter/src/rules/react_perf/jsx_no_new_array_as_prop.rs +++ b/crates/oxc_linter/src/rules/react_perf/jsx_no_new_array_as_prop.rs @@ -46,6 +46,9 @@ declare_oxc_lint!( impl Rule for JsxNoNewArrayAsProp { fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { + if node.scope_id() == ctx.scopes().root_scope_id() { + return; + } if let AstKind::JSXElement(jsx_elem) = node.kind() { check_jsx_element(jsx_elem, ctx); } @@ -103,9 +106,9 @@ fn check_expression(expr: &Expression) -> Option { fn test() { use crate::tester::Tester; - let pass = vec![r""]; - - let fail = vec![ + let pass = vec![ + r"", + r"const Foo = () => ", r"", r"", r"", @@ -114,6 +117,15 @@ fn test() { r"", ]; + let fail = vec![ + r"const Foo = () => ()", + r"const Foo = () => ()", + r"const Foo = () => ()", + r"const Foo = () => ()", + r"const Foo = () => ()", + r"const Foo = () => ()", + ]; + Tester::new(JsxNoNewArrayAsProp::NAME, pass, fail) .with_react_perf_plugin(true) .test_and_snapshot(); diff --git a/crates/oxc_linter/src/rules/react_perf/jsx_no_new_function_as_prop.rs b/crates/oxc_linter/src/rules/react_perf/jsx_no_new_function_as_prop.rs index 4540409e7ba9d..ce86756e1fa63 100644 --- a/crates/oxc_linter/src/rules/react_perf/jsx_no_new_function_as_prop.rs +++ b/crates/oxc_linter/src/rules/react_perf/jsx_no_new_function_as_prop.rs @@ -41,6 +41,9 @@ declare_oxc_lint!( impl Rule for JsxNoNewFunctionAsProp { fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { + if node.scope_id() == ctx.scopes().root_scope_id() { + return; + } if let AstKind::JSXElement(jsx_elem) = node.kind() { check_jsx_element(jsx_elem, ctx); } @@ -106,22 +109,19 @@ fn test() { use crate::tester::Tester; let pass = vec![ - r"", - r"", - r"", - r"", - r"var a;", - r"var a;a = 1;", - r"var a;", + r"const Foo = () => ", + r"const Foo = () => ()", + r"const Foo = () => ()", + r"const Foo = () => ()", + r"const Foo = () => { var a; return }", + r"const Foo = () => { var a;a = 1; return }", + r"const Foo = () => { var a; }", r"function foo ({prop1 = function(){}, prop2}) { return }", r"function foo ({prop1, prop2 = function(){}}) { return }", - ]; - - let fail = vec![ r"", r" true} />", r"", @@ -133,6 +133,18 @@ fn test() { r"", ]; + let fail = vec![ + r"const Foo = () => ()", + r"const Foo = () => ( true} />)", + r"const Foo = () => ()", + r"const Foo = () => ()", + r"const Foo = () => ()", + r"const Foo = () => ()", + r"const Foo = () => ()", + r"const Foo = () => ()", + r"const Foo = () => ()", + ]; + Tester::new(JsxNoNewFunctionAsProp::NAME, pass, fail) .with_react_perf_plugin(true) .test_and_snapshot(); diff --git a/crates/oxc_linter/src/rules/react_perf/jsx_no_new_object_as_prop.rs b/crates/oxc_linter/src/rules/react_perf/jsx_no_new_object_as_prop.rs index e679923f6c08b..c470f9f91c90a 100644 --- a/crates/oxc_linter/src/rules/react_perf/jsx_no_new_object_as_prop.rs +++ b/crates/oxc_linter/src/rules/react_perf/jsx_no_new_object_as_prop.rs @@ -45,6 +45,9 @@ declare_oxc_lint!( impl Rule for JsxNoNewObjectAsProp { fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { + if node.scope_id() == ctx.scopes().root_scope_id() { + return; + } if let AstKind::JSXElement(jsx_elem) = node.kind() { check_jsx_element(jsx_elem, ctx); } @@ -102,16 +105,20 @@ fn check_expression(expr: &Expression) -> Option { fn test() { use crate::tester::Tester; - let pass = vec![r""]; + let pass = vec![ + r"", + r"", + r"const Foo = () => ", + ]; let fail = vec![ - r"", - r"", - r"", - r"
", - r"", - r"", - r"", + r"const Foo = () => ", + r"const Foo = () => ()", + r"const Foo = () => ()", + r"const Foo = () => (
)", + r"const Foo = () => ()", + r"const Foo = () => ()", + r"const Foo = () => ()", ]; Tester::new(JsxNoNewObjectAsProp::NAME, pass, fail) 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 index aeef267e41c08..1efa1bd9509f4 100644 --- a/crates/oxc_linter/src/snapshots/jsx_no_jsx_as_prop.snap +++ b/crates/oxc_linter/src/snapshots/jsx_no_jsx_as_prop.snap @@ -2,29 +2,29 @@ source: crates/oxc_linter/src/tester.rs --- ⚠ eslint-plugin-react-perf(jsx-no-jsx-as-prop): JSX attribute values should not contain other JSX. - ╭─[jsx_no_jsx_as_prop.tsx:1:12] - 1 │ } /> - · ─────────── + ╭─[jsx_no_jsx_as_prop.tsx:1:31] + 1 │ const Foo = () => (} />) + · ─────────── ╰──── 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:30] - 1 │ } /> - · ─────────── + ╭─[jsx_no_jsx_as_prop.tsx:1:49] + 1 │ const Foo = () => (} />) + · ─────────── ╰──── 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:46] - 1 │ } /> - · ─────────── + ╭─[jsx_no_jsx_as_prop.tsx:1:65] + 1 │ const Foo = () => (} />) + · ─────────── ╰──── 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:77] - 1 │ )} /> - · ─────────── + ╭─[jsx_no_jsx_as_prop.tsx:1:96] + 1 │ const Foo = () => ()} />) + · ─────────── ╰──── 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 index 6525428584849..b1f691bca6e8f 100644 --- 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 @@ -2,43 +2,43 @@ source: crates/oxc_linter/src/tester.rs --- ⚠ 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:13] - 1 │ - · ── + ╭─[jsx_no_new_array_as_prop.tsx:1:32] + 1 │ const Foo = () => () + · ── ╰──── 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:13] - 1 │ - · ─────────── + ╭─[jsx_no_new_array_as_prop.tsx:1:32] + 1 │ const Foo = () => () + · ─────────── ╰──── 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:13] - 1 │ - · ─────── + ╭─[jsx_no_new_array_as_prop.tsx:1:32] + 1 │ const Foo = () => () + · ─────── ╰──── 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:32] - 1 │ - · ── + ╭─[jsx_no_new_array_as_prop.tsx:1:51] + 1 │ const Foo = () => () + · ── ╰──── 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:49] - 1 │ - · ── + ╭─[jsx_no_new_array_as_prop.tsx:1:68] + 1 │ const Foo = () => () + · ── ╰──── 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:67] - 1 │ - · ── + ╭─[jsx_no_new_array_as_prop.tsx:1:86] + 1 │ const Foo = () => () + · ── ╰──── 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_prop.snap b/crates/oxc_linter/src/snapshots/jsx_no_new_function_as_prop.snap index 7c24174043b4f..42bb3b357a576 100644 --- a/crates/oxc_linter/src/snapshots/jsx_no_new_function_as_prop.snap +++ b/crates/oxc_linter/src/snapshots/jsx_no_new_function_as_prop.snap @@ -2,64 +2,64 @@ source: crates/oxc_linter/src/tester.rs --- ⚠ eslint-plugin-react-perf(jsx-no-new-function-as-prop): JSX attribute values should not contain functions created in the same scope. - ╭─[jsx_no_new_function_as_prop.tsx:1:13] - 1 │ - · ─────────────────────── + ╭─[jsx_no_new_function_as_prop.tsx:1:32] + 1 │ const Foo = () => () + · ─────────────────────── ╰──── 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-prop): JSX attribute values should not contain functions created in the same scope. - ╭─[jsx_no_new_function_as_prop.tsx:1:13] - 1 │ true} /> - · ────────── + ╭─[jsx_no_new_function_as_prop.tsx:1:32] + 1 │ const Foo = () => ( 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-prop): JSX attribute values should not contain functions created in the same scope. - ╭─[jsx_no_new_function_as_prop.tsx:1:13] - 1 │ - · ───────────────────────────── + ╭─[jsx_no_new_function_as_prop.tsx:1:32] + 1 │ const Foo = () => () + · ───────────────────────────── ╰──── 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-prop): JSX attribute values should not contain functions created in the same scope. - ╭─[jsx_no_new_function_as_prop.tsx:1:13] - 1 │ - · ────────── + ╭─[jsx_no_new_function_as_prop.tsx:1:32] + 1 │ const Foo = () => () + · ────────── ╰──── 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-prop): JSX attribute values should not contain functions created in the same scope. - ╭─[jsx_no_new_function_as_prop.tsx:1:16] - 1 │ - · ──────────────────────────── + ╭─[jsx_no_new_function_as_prop.tsx:1:35] + 1 │ const Foo = () => () + · ──────────────────────────── ╰──── 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-prop): JSX attribute values should not contain functions created in the same scope. - ╭─[jsx_no_new_function_as_prop.tsx:1:40] - 1 │ - · ───────────── + ╭─[jsx_no_new_function_as_prop.tsx:1:59] + 1 │ const Foo = () => () + · ───────────── ╰──── 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-prop): JSX attribute values should not contain functions created in the same scope. - ╭─[jsx_no_new_function_as_prop.tsx:1:61] - 1 │ - · ───────────── + ╭─[jsx_no_new_function_as_prop.tsx:1:80] + 1 │ const Foo = () => () + · ───────────── ╰──── 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-prop): JSX attribute values should not contain functions created in the same scope. - ╭─[jsx_no_new_function_as_prop.tsx:1:80] - 1 │ - · ──────────── + ╭─[jsx_no_new_function_as_prop.tsx:1:99] + 1 │ const Foo = () => () + · ──────────── ╰──── 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-prop): JSX attribute values should not contain functions created in the same scope. - ╭─[jsx_no_new_function_as_prop.tsx:1:69] - 1 │ - · ──────────── + ╭─[jsx_no_new_function_as_prop.tsx:1:88] + 1 │ const Foo = () => () + · ──────────── ╰──── 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 index b999c6e261638..f1de1ecde019d 100644 --- 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 @@ -2,50 +2,50 @@ source: crates/oxc_linter/src/tester.rs --- ⚠ 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:15] - 1 │ - · ── + ╭─[jsx_no_new_object_as_prop.tsx:1:33] + 1 │ const Foo = () => + · ── ╰──── 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:15] - 1 │ - · ──────────── + ╭─[jsx_no_new_object_as_prop.tsx:1:34] + 1 │ const Foo = () => () + · ──────────── ╰──── 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:15] - 1 │ - · ──────── + ╭─[jsx_no_new_object_as_prop.tsx:1:34] + 1 │ const Foo = () => () + · ──────── ╰──── 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:13] - 1 │
- · ───────────────── + ╭─[jsx_no_new_object_as_prop.tsx:1:32] + 1 │ const Foo = () => (
) + · ───────────────── ╰──── 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:36] - 1 │ - · ── + ╭─[jsx_no_new_object_as_prop.tsx:1:55] + 1 │ const Foo = () => () + · ── ╰──── 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:55] - 1 │ - · ── + ╭─[jsx_no_new_object_as_prop.tsx:1:74] + 1 │ const Foo = () => () + · ── ╰──── 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:79] - 1 │ - · ── + ╭─[jsx_no_new_object_as_prop.tsx:1:98] + 1 │ const Foo = () => () + · ── ╰──── 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_semantic/src/scope.rs b/crates/oxc_semantic/src/scope.rs index 802b52df7707e..4f16838d1238d 100644 --- a/crates/oxc_semantic/src/scope.rs +++ b/crates/oxc_semantic/src/scope.rs @@ -32,6 +32,8 @@ pub struct ScopeTree { } impl ScopeTree { + const ROOT_SCOPE_ID: ScopeId = ScopeId::from_usize_unchecked(0); + pub fn len(&self) -> usize { self.parent_ids.len() } @@ -80,8 +82,8 @@ impl ScopeTree { } #[inline] - pub fn root_scope_id(&self) -> ScopeId { - ScopeId::new(0) + pub const fn root_scope_id(&self) -> ScopeId { + Self::ROOT_SCOPE_ID } pub fn root_flags(&self) -> ScopeFlags {