diff --git a/crates/rome_js_analyze/src/react.rs b/crates/rome_js_analyze/src/react.rs index dbede90cd8a..0566fcbeb5a 100644 --- a/crates/rome_js_analyze/src/react.rs +++ b/crates/rome_js_analyze/src/react.rs @@ -55,7 +55,8 @@ impl ReactCreateElementCall { model: &SemanticModel, ) -> Option { let callee = call_expression.callee().ok()?; - let is_react_create_element = is_react_call_api(&callee, model, "createElement")?; + let is_react_create_element = + is_react_call_api(&callee, model, ReactLibrary::React, "createElement")?; if is_react_create_element { let arguments = call_expression.arguments().ok()?.args(); @@ -156,7 +157,8 @@ impl ReactCloneElementCall { model: &SemanticModel, ) -> Option { let callee = call_expression.callee().ok()?; - let is_react_clone_element = is_react_call_api(&callee, model, "cloneElement")?; + let is_react_clone_element = + is_react_call_api(&callee, model, ReactLibrary::React, "cloneElement")?; if is_react_clone_element { let arguments = call_expression.arguments().ok()?.args(); @@ -216,6 +218,28 @@ impl ReactApiCall for ReactCloneElementCall { } } +#[derive(Debug, Clone, Copy)] +pub(crate) enum ReactLibrary { + React, + ReactDOM, +} + +impl ReactLibrary { + const fn import_name(self) -> &'static str { + match self { + ReactLibrary::React => "react", + ReactLibrary::ReactDOM => "react-dom", + } + } + + const fn global_name(self) -> &'static str { + match self { + ReactLibrary::React => "React", + ReactLibrary::ReactDOM => "ReactDOM", + } + } +} + /// List of valid [`React` API] /// /// [`React` API]: https://reactjs.org/docs/react-api.html @@ -243,10 +267,13 @@ const VALID_REACT_API: [&str; 14] = [ pub(crate) fn is_react_call_api( expression: &JsAnyExpression, model: &SemanticModel, + lib: ReactLibrary, api_name: &str, ) -> Option { - // we bail straight away if the API doesn't exists in React - debug_assert!(VALID_REACT_API.contains(&api_name)); + if matches!(lib, ReactLibrary::React) { + // we bail straight away if the API doesn't exists in React + debug_assert!(VALID_REACT_API.contains(&api_name)); + } Some(match expression { JsAnyExpression::JsStaticMemberExpression(node) => { @@ -269,12 +296,12 @@ pub(crate) fn is_react_call_api( .ancestors() .find_map(|ancestor| JsImport::cast_ref(&ancestor)) { - js_import.source_is("react").ok()? + js_import.source_is(lib.import_name()).ok()? } else { false } } - None => identifier.has_name("React"), + None => identifier.has_name(lib.global_name()), } } @@ -283,7 +310,7 @@ pub(crate) fn is_react_call_api( model .declaration(&name) - .and_then(|binding| is_react_export(binding, api_name)) + .and_then(|binding| is_react_export(binding, lib, api_name)) .unwrap_or(false) } _ => false, @@ -335,7 +362,7 @@ pub(crate) fn jsx_reference_identifier_is_fragment( model: &SemanticModel, ) -> Option { match model.declaration(name) { - Some(reference) => is_react_export(reference, "Fragment"), + Some(reference) => is_react_export(reference, ReactLibrary::React, "Fragment"), None => { let value_token = name.value_token().ok()?; let is_fragment = value_token.text_trimmed() == "Fragment"; @@ -344,7 +371,7 @@ pub(crate) fn jsx_reference_identifier_is_fragment( } } -fn is_react_export(binding: Binding, name: &str) -> Option { +fn is_react_export(binding: Binding, lib: ReactLibrary, name: &str) -> Option { let ident = JsIdentifierBinding::cast_ref(binding.syntax())?; let import_specifier = ident.parent::()?; let name_token = match &import_specifier { @@ -366,5 +393,5 @@ fn is_react_export(binding: Binding, name: &str) -> Option { let import_clause = import_specifiers.parent::()?; let import = import_clause.parent::()?; - import.source_is("react").ok() + import.source_is(lib.import_name()).ok() } diff --git a/crates/rome_js_analyze/src/semantic_analyzers/correctness/no_array_index_key.rs b/crates/rome_js_analyze/src/semantic_analyzers/correctness/no_array_index_key.rs index 1ca2a3c2257..14a42eb75d3 100644 --- a/crates/rome_js_analyze/src/semantic_analyzers/correctness/no_array_index_key.rs +++ b/crates/rome_js_analyze/src/semantic_analyzers/correctness/no_array_index_key.rs @@ -1,4 +1,4 @@ -use crate::react::{is_react_call_api, ReactApiCall, ReactCloneElementCall}; +use crate::react::{is_react_call_api, ReactApiCall, ReactCloneElementCall, ReactLibrary}; use crate::semantic_services::Semantic; use rome_analyze::context::RuleContext; use rome_analyze::{declare_rule, Rule, RuleDiagnostic}; @@ -333,7 +333,7 @@ fn find_react_children_function_argument( let object = member_expression.object().ok()?; // React.Children.forEach/map or Children.forEach/map - if is_react_call_api(&object, model, "Children")? { + if is_react_call_api(&object, model, ReactLibrary::React, "Children")? { let arguments = call_expression.arguments().ok()?; let arguments = arguments.args(); let mut arguments = arguments.into_iter(); diff --git a/crates/rome_js_analyze/src/semantic_analyzers/correctness/no_render_return_value.rs b/crates/rome_js_analyze/src/semantic_analyzers/correctness/no_render_return_value.rs index 38f00073b2c..967d68da68d 100644 --- a/crates/rome_js_analyze/src/semantic_analyzers/correctness/no_render_return_value.rs +++ b/crates/rome_js_analyze/src/semantic_analyzers/correctness/no_render_return_value.rs @@ -1,14 +1,10 @@ +use crate::react::{is_react_call_api, ReactLibrary}; use crate::semantic_services::Semantic; use rome_analyze::context::RuleContext; use rome_analyze::{declare_rule, Rule, RuleDiagnostic}; use rome_console::markup; -use rome_js_semantic::SemanticModel; -use rome_js_syntax::JsSyntaxKind::JS_IMPORT; -use rome_js_syntax::{ - JsAnyExpression, JsCallExpression, JsExpressionStatement, JsIdentifierBinding, - JsIdentifierExpression, JsStaticMemberExpression, -}; -use rome_rowan::{declare_node_union, AstNode}; +use rome_js_syntax::{JsCallExpression, JsExpressionStatement}; +use rome_rowan::AstNode; declare_rule! { /// Prevent the usage of the return value of `React.render`. @@ -50,16 +46,7 @@ impl Rule for NoRenderReturnValue { let node = ctx.query(); let callee = node.callee().ok()?; let model = ctx.model(); - let is_react_render = match callee { - JsAnyExpression::JsStaticMemberExpression(static_member) => { - is_react_render(PossibleReactRender::from(static_member), model) - } - JsAnyExpression::JsIdentifierExpression(identifier_expression) => { - is_react_render(PossibleReactRender::from(identifier_expression), model) - } - _ => return None, - }?; - if is_react_render { + if is_react_call_api(&callee, model, ReactLibrary::ReactDOM, "render")? { let parent = node.syntax().parent()?; if !JsExpressionStatement::can_cast(parent.kind()) { @@ -85,60 +72,3 @@ Check the " { - let maybe_react_render = identifier.syntax().text_trimmed() == "render"; - let name = identifier.name().ok()?; - if maybe_react_render { - let declaration = model.declaration(&name); - if let Some(declaration) = declaration { - let identifier_binding = JsIdentifierBinding::cast_ref(declaration.syntax())?; - for ancestor in identifier_binding.syntax().ancestors() { - if ancestor.kind() == JS_IMPORT { - return Some( - identifier_binding.syntax().text_trimmed() - == identifier.syntax().text_trimmed(), - ); - } - } - } - } - - maybe_react_render - } - }; - - Some(result) -} diff --git a/crates/rome_js_analyze/tests/specs/correctness/noRenderReturnValue.jsx.snap b/crates/rome_js_analyze/tests/specs/correctness/noRenderReturnValue.jsx.snap deleted file mode 100644 index 5ab967c523a..00000000000 --- a/crates/rome_js_analyze/tests/specs/correctness/noRenderReturnValue.jsx.snap +++ /dev/null @@ -1,159 +0,0 @@ ---- -source: crates/rome_js_analyze/tests/spec_tests.rs -expression: noRenderReturnValue.jsx ---- -# Input -```js -// invalid -const a = ReactDOM.render(
, document.body); -const foo = bar && ReactDOM.render(
, document.body); -const foo = bar ? ReactDOM.render(
, document.body) : null -const foo = () => ReactDOM.render(
, document.body); -const foo = { - react: ReactDOM.render(
, document.body) -}; -let lorem; -lorem = ReactDOM.render(
, document.body); -function render () { - return ReactDOM.render(
, document.body) -} - -// valid -ReactDOM.render(
, document.body); -function render () { - ReactDOM.render(
, document.body); -} -const render = () => { - ReactDOM.render(
, document.body); -} - - -``` - -# Diagnostics -``` -noRenderReturnValue.jsx:2:11 lint/correctness/noRenderReturnValue ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Do not depend on the value returned by the function ReactDOM.render(). - - 1 │ // invalid - > 2 │ const a = ReactDOM.render(
, document.body); - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - 3 │ const foo = bar && ReactDOM.render(
, document.body); - 4 │ const foo = bar ? ReactDOM.render(
, document.body) : null - - i The returned value is legacy and future versions of react might return that value asynchronously. - Check the React documentation for more information. - - -``` - -``` -noRenderReturnValue.jsx:3:20 lint/correctness/noRenderReturnValue ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Do not depend on the value returned by the function ReactDOM.render(). - - 1 │ // invalid - 2 │ const a = ReactDOM.render(
, document.body); - > 3 │ const foo = bar && ReactDOM.render(
, document.body); - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - 4 │ const foo = bar ? ReactDOM.render(
, document.body) : null - 5 │ const foo = () => ReactDOM.render(
, document.body); - - i The returned value is legacy and future versions of react might return that value asynchronously. - Check the React documentation for more information. - - -``` - -``` -noRenderReturnValue.jsx:4:19 lint/correctness/noRenderReturnValue ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Do not depend on the value returned by the function ReactDOM.render(). - - 2 │ const a = ReactDOM.render(
, document.body); - 3 │ const foo = bar && ReactDOM.render(
, document.body); - > 4 │ const foo = bar ? ReactDOM.render(
, document.body) : null - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - 5 │ const foo = () => ReactDOM.render(
, document.body); - 6 │ const foo = { - - i The returned value is legacy and future versions of react might return that value asynchronously. - Check the React documentation for more information. - - -``` - -``` -noRenderReturnValue.jsx:5:19 lint/correctness/noRenderReturnValue ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Do not depend on the value returned by the function ReactDOM.render(). - - 3 │ const foo = bar && ReactDOM.render(
, document.body); - 4 │ const foo = bar ? ReactDOM.render(
, document.body) : null - > 5 │ const foo = () => ReactDOM.render(
, document.body); - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - 6 │ const foo = { - 7 │ react: ReactDOM.render(
, document.body) - - i The returned value is legacy and future versions of react might return that value asynchronously. - Check the React documentation for more information. - - -``` - -``` -noRenderReturnValue.jsx:7:12 lint/correctness/noRenderReturnValue ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Do not depend on the value returned by the function ReactDOM.render(). - - 5 │ const foo = () => ReactDOM.render(
, document.body); - 6 │ const foo = { - > 7 │ react: ReactDOM.render(
, document.body) - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - 8 │ }; - 9 │ let lorem; - - i The returned value is legacy and future versions of react might return that value asynchronously. - Check the React documentation for more information. - - -``` - -``` -noRenderReturnValue.jsx:10:9 lint/correctness/noRenderReturnValue ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Do not depend on the value returned by the function ReactDOM.render(). - - 8 │ }; - 9 │ let lorem; - > 10 │ lorem = ReactDOM.render(
, document.body); - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - 11 │ function render () { - 12 │ return ReactDOM.render(
, document.body) - - i The returned value is legacy and future versions of react might return that value asynchronously. - Check the React documentation for more information. - - -``` - -``` -noRenderReturnValue.jsx:12:12 lint/correctness/noRenderReturnValue ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! Do not depend on the value returned by the function ReactDOM.render(). - - 10 │ lorem = ReactDOM.render(
, document.body); - 11 │ function render () { - > 12 │ return ReactDOM.render(
, document.body) - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - 13 │ } - 14 │ - - i The returned value is legacy and future versions of react might return that value asynchronously. - Check the React documentation for more information. - - -``` - - diff --git a/crates/rome_js_analyze/tests/specs/correctness/noRenderReturnValue.jsx b/crates/rome_js_analyze/tests/specs/correctness/noRenderReturnValue/invalidGlobal.tsx similarity index 65% rename from crates/rome_js_analyze/tests/specs/correctness/noRenderReturnValue.jsx rename to crates/rome_js_analyze/tests/specs/correctness/noRenderReturnValue/invalidGlobal.tsx index 9de61551ff2..6e77e501ee7 100644 --- a/crates/rome_js_analyze/tests/specs/correctness/noRenderReturnValue.jsx +++ b/crates/rome_js_analyze/tests/specs/correctness/noRenderReturnValue/invalidGlobal.tsx @@ -1,4 +1,3 @@ -// invalid const a = ReactDOM.render(
, document.body); const foo = bar && ReactDOM.render(
, document.body); const foo = bar ? ReactDOM.render(
, document.body) : null @@ -8,16 +7,6 @@ const foo = { }; let lorem; lorem = ReactDOM.render(
, document.body); -function render () { +function render() { return ReactDOM.render(
, document.body) } - -// valid -ReactDOM.render(
, document.body); -function render () { - ReactDOM.render(
, document.body); -} -const render = () => { - ReactDOM.render(
, document.body); -} - diff --git a/crates/rome_js_analyze/tests/specs/correctness/noRenderReturnValue/invalidGlobal.tsx.snap b/crates/rome_js_analyze/tests/specs/correctness/noRenderReturnValue/invalidGlobal.tsx.snap new file mode 100644 index 00000000000..c500e1c343e --- /dev/null +++ b/crates/rome_js_analyze/tests/specs/correctness/noRenderReturnValue/invalidGlobal.tsx.snap @@ -0,0 +1,146 @@ +--- +source: crates/rome_js_analyze/tests/spec_tests.rs +expression: invalidGlobal.tsx +--- +# Input +```js +const a = ReactDOM.render(
, document.body); +const foo = bar && ReactDOM.render(
, document.body); +const foo = bar ? ReactDOM.render(
, document.body) : null +const foo = () => ReactDOM.render(
, document.body); +const foo = { + react: ReactDOM.render(
, document.body) +}; +let lorem; +lorem = ReactDOM.render(
, document.body); +function render() { + return ReactDOM.render(
, document.body) +} + +``` + +# Diagnostics +``` +invalidGlobal.tsx:1:11 lint/correctness/noRenderReturnValue ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Do not depend on the value returned by the function ReactDOM.render(). + + > 1 │ const a = ReactDOM.render(
, document.body); + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 2 │ const foo = bar && ReactDOM.render(
, document.body); + 3 │ const foo = bar ? ReactDOM.render(
, document.body) : null + + i The returned value is legacy and future versions of react might return that value asynchronously. + Check the React documentation for more information. + + +``` + +``` +invalidGlobal.tsx:2:20 lint/correctness/noRenderReturnValue ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Do not depend on the value returned by the function ReactDOM.render(). + + 1 │ const a = ReactDOM.render(
, document.body); + > 2 │ const foo = bar && ReactDOM.render(
, document.body); + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 3 │ const foo = bar ? ReactDOM.render(
, document.body) : null + 4 │ const foo = () => ReactDOM.render(
, document.body); + + i The returned value is legacy and future versions of react might return that value asynchronously. + Check the React documentation for more information. + + +``` + +``` +invalidGlobal.tsx:3:19 lint/correctness/noRenderReturnValue ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Do not depend on the value returned by the function ReactDOM.render(). + + 1 │ const a = ReactDOM.render(
, document.body); + 2 │ const foo = bar && ReactDOM.render(
, document.body); + > 3 │ const foo = bar ? ReactDOM.render(
, document.body) : null + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 4 │ const foo = () => ReactDOM.render(
, document.body); + 5 │ const foo = { + + i The returned value is legacy and future versions of react might return that value asynchronously. + Check the React documentation for more information. + + +``` + +``` +invalidGlobal.tsx:4:19 lint/correctness/noRenderReturnValue ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Do not depend on the value returned by the function ReactDOM.render(). + + 2 │ const foo = bar && ReactDOM.render(
, document.body); + 3 │ const foo = bar ? ReactDOM.render(
, document.body) : null + > 4 │ const foo = () => ReactDOM.render(
, document.body); + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 5 │ const foo = { + 6 │ react: ReactDOM.render(
, document.body) + + i The returned value is legacy and future versions of react might return that value asynchronously. + Check the React documentation for more information. + + +``` + +``` +invalidGlobal.tsx:6:12 lint/correctness/noRenderReturnValue ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Do not depend on the value returned by the function ReactDOM.render(). + + 4 │ const foo = () => ReactDOM.render(
, document.body); + 5 │ const foo = { + > 6 │ react: ReactDOM.render(
, document.body) + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 7 │ }; + 8 │ let lorem; + + i The returned value is legacy and future versions of react might return that value asynchronously. + Check the React documentation for more information. + + +``` + +``` +invalidGlobal.tsx:9:9 lint/correctness/noRenderReturnValue ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Do not depend on the value returned by the function ReactDOM.render(). + + 7 │ }; + 8 │ let lorem; + > 9 │ lorem = ReactDOM.render(
, document.body); + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 10 │ function render() { + 11 │ return ReactDOM.render(
, document.body) + + i The returned value is legacy and future versions of react might return that value asynchronously. + Check the React documentation for more information. + + +``` + +``` +invalidGlobal.tsx:11:12 lint/correctness/noRenderReturnValue ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Do not depend on the value returned by the function ReactDOM.render(). + + 9 │ lorem = ReactDOM.render(
, document.body); + 10 │ function render() { + > 11 │ return ReactDOM.render(
, document.body) + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 12 │ } + 13 │ + + i The returned value is legacy and future versions of react might return that value asynchronously. + Check the React documentation for more information. + + +``` + + diff --git a/crates/rome_js_analyze/tests/specs/correctness/noRenderReturnValue/invalidImport.tsx b/crates/rome_js_analyze/tests/specs/correctness/noRenderReturnValue/invalidImport.tsx new file mode 100644 index 00000000000..d1cf638aa7f --- /dev/null +++ b/crates/rome_js_analyze/tests/specs/correctness/noRenderReturnValue/invalidImport.tsx @@ -0,0 +1,27 @@ +import CustomReactDOM, { render as customRender } from "react-dom"; + +const a = CustomReactDOM.render(
, document.body); +const foo = bar && CustomReactDOM.render(
, document.body); +const foo = bar ? CustomReactDOM.render(
, document.body) : null +const foo = () => CustomReactDOM.render(
, document.body); +const foo = { + react: CustomReactDOM.render(
, document.body) +}; +let lorem; +lorem = CustomReactDOM.render(
, document.body); +function render1() { + return CustomReactDOM.render(
, document.body) +} + +const a = customRender(
, document.body); +const foo = bar && customRender(
, document.body); +const foo = bar ? customRender(
, document.body) : null +const foo = () => customRender(
, document.body); +const foo = { + react: customRender(
, document.body) +}; +let lorem; +lorem = customRender(
, document.body); +function render2() { + return customRender(
, document.body) +} diff --git a/crates/rome_js_analyze/tests/specs/correctness/noRenderReturnValue/invalidImport.tsx.snap b/crates/rome_js_analyze/tests/specs/correctness/noRenderReturnValue/invalidImport.tsx.snap new file mode 100644 index 00000000000..cae05544dbb --- /dev/null +++ b/crates/rome_js_analyze/tests/specs/correctness/noRenderReturnValue/invalidImport.tsx.snap @@ -0,0 +1,288 @@ +--- +source: crates/rome_js_analyze/tests/spec_tests.rs +expression: invalidImport.tsx +--- +# Input +```js +import CustomReactDOM, { render as customRender } from "react-dom"; + +const a = CustomReactDOM.render(
, document.body); +const foo = bar && CustomReactDOM.render(
, document.body); +const foo = bar ? CustomReactDOM.render(
, document.body) : null +const foo = () => CustomReactDOM.render(
, document.body); +const foo = { + react: CustomReactDOM.render(
, document.body) +}; +let lorem; +lorem = CustomReactDOM.render(
, document.body); +function render1() { + return CustomReactDOM.render(
, document.body) +} + +const a = customRender(
, document.body); +const foo = bar && customRender(
, document.body); +const foo = bar ? customRender(
, document.body) : null +const foo = () => customRender(
, document.body); +const foo = { + react: customRender(
, document.body) +}; +let lorem; +lorem = customRender(
, document.body); +function render2() { + return customRender(
, document.body) +} + +``` + +# Diagnostics +``` +invalidImport.tsx:3:11 lint/correctness/noRenderReturnValue ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Do not depend on the value returned by the function ReactDOM.render(). + + 1 │ import CustomReactDOM, { render as customRender } from "react-dom"; + 2 │ + > 3 │ const a = CustomReactDOM.render(
, document.body); + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 4 │ const foo = bar && CustomReactDOM.render(
, document.body); + 5 │ const foo = bar ? CustomReactDOM.render(
, document.body) : null + + i The returned value is legacy and future versions of react might return that value asynchronously. + Check the React documentation for more information. + + +``` + +``` +invalidImport.tsx:4:20 lint/correctness/noRenderReturnValue ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Do not depend on the value returned by the function ReactDOM.render(). + + 3 │ const a = CustomReactDOM.render(
, document.body); + > 4 │ const foo = bar && CustomReactDOM.render(
, document.body); + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 5 │ const foo = bar ? CustomReactDOM.render(
, document.body) : null + 6 │ const foo = () => CustomReactDOM.render(
, document.body); + + i The returned value is legacy and future versions of react might return that value asynchronously. + Check the React documentation for more information. + + +``` + +``` +invalidImport.tsx:5:19 lint/correctness/noRenderReturnValue ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Do not depend on the value returned by the function ReactDOM.render(). + + 3 │ const a = CustomReactDOM.render(
, document.body); + 4 │ const foo = bar && CustomReactDOM.render(
, document.body); + > 5 │ const foo = bar ? CustomReactDOM.render(
, document.body) : null + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 6 │ const foo = () => CustomReactDOM.render(
, document.body); + 7 │ const foo = { + + i The returned value is legacy and future versions of react might return that value asynchronously. + Check the React documentation for more information. + + +``` + +``` +invalidImport.tsx:6:19 lint/correctness/noRenderReturnValue ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Do not depend on the value returned by the function ReactDOM.render(). + + 4 │ const foo = bar && CustomReactDOM.render(
, document.body); + 5 │ const foo = bar ? CustomReactDOM.render(
, document.body) : null + > 6 │ const foo = () => CustomReactDOM.render(
, document.body); + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 7 │ const foo = { + 8 │ react: CustomReactDOM.render(
, document.body) + + i The returned value is legacy and future versions of react might return that value asynchronously. + Check the React documentation for more information. + + +``` + +``` +invalidImport.tsx:8:12 lint/correctness/noRenderReturnValue ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Do not depend on the value returned by the function ReactDOM.render(). + + 6 │ const foo = () => CustomReactDOM.render(
, document.body); + 7 │ const foo = { + > 8 │ react: CustomReactDOM.render(
, document.body) + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 9 │ }; + 10 │ let lorem; + + i The returned value is legacy and future versions of react might return that value asynchronously. + Check the React documentation for more information. + + +``` + +``` +invalidImport.tsx:11:9 lint/correctness/noRenderReturnValue ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Do not depend on the value returned by the function ReactDOM.render(). + + 9 │ }; + 10 │ let lorem; + > 11 │ lorem = CustomReactDOM.render(
, document.body); + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 12 │ function render1() { + 13 │ return CustomReactDOM.render(
, document.body) + + i The returned value is legacy and future versions of react might return that value asynchronously. + Check the React documentation for more information. + + +``` + +``` +invalidImport.tsx:13:12 lint/correctness/noRenderReturnValue ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Do not depend on the value returned by the function ReactDOM.render(). + + 11 │ lorem = CustomReactDOM.render(
, document.body); + 12 │ function render1() { + > 13 │ return CustomReactDOM.render(
, document.body) + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 14 │ } + 15 │ + + i The returned value is legacy and future versions of react might return that value asynchronously. + Check the React documentation for more information. + + +``` + +``` +invalidImport.tsx:16:11 lint/correctness/noRenderReturnValue ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Do not depend on the value returned by the function ReactDOM.render(). + + 14 │ } + 15 │ + > 16 │ const a = customRender(
, document.body); + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 17 │ const foo = bar && customRender(
, document.body); + 18 │ const foo = bar ? customRender(
, document.body) : null + + i The returned value is legacy and future versions of react might return that value asynchronously. + Check the React documentation for more information. + + +``` + +``` +invalidImport.tsx:17:20 lint/correctness/noRenderReturnValue ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Do not depend on the value returned by the function ReactDOM.render(). + + 16 │ const a = customRender(
, document.body); + > 17 │ const foo = bar && customRender(
, document.body); + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 18 │ const foo = bar ? customRender(
, document.body) : null + 19 │ const foo = () => customRender(
, document.body); + + i The returned value is legacy and future versions of react might return that value asynchronously. + Check the React documentation for more information. + + +``` + +``` +invalidImport.tsx:18:19 lint/correctness/noRenderReturnValue ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Do not depend on the value returned by the function ReactDOM.render(). + + 16 │ const a = customRender(
, document.body); + 17 │ const foo = bar && customRender(
, document.body); + > 18 │ const foo = bar ? customRender(
, document.body) : null + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 19 │ const foo = () => customRender(
, document.body); + 20 │ const foo = { + + i The returned value is legacy and future versions of react might return that value asynchronously. + Check the React documentation for more information. + + +``` + +``` +invalidImport.tsx:19:19 lint/correctness/noRenderReturnValue ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Do not depend on the value returned by the function ReactDOM.render(). + + 17 │ const foo = bar && customRender(
, document.body); + 18 │ const foo = bar ? customRender(
, document.body) : null + > 19 │ const foo = () => customRender(
, document.body); + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 20 │ const foo = { + 21 │ react: customRender(
, document.body) + + i The returned value is legacy and future versions of react might return that value asynchronously. + Check the React documentation for more information. + + +``` + +``` +invalidImport.tsx:21:12 lint/correctness/noRenderReturnValue ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Do not depend on the value returned by the function ReactDOM.render(). + + 19 │ const foo = () => customRender(
, document.body); + 20 │ const foo = { + > 21 │ react: customRender(
, document.body) + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 22 │ }; + 23 │ let lorem; + + i The returned value is legacy and future versions of react might return that value asynchronously. + Check the React documentation for more information. + + +``` + +``` +invalidImport.tsx:24:9 lint/correctness/noRenderReturnValue ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Do not depend on the value returned by the function ReactDOM.render(). + + 22 │ }; + 23 │ let lorem; + > 24 │ lorem = customRender(
, document.body); + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 25 │ function render2() { + 26 │ return customRender(
, document.body) + + i The returned value is legacy and future versions of react might return that value asynchronously. + Check the React documentation for more information. + + +``` + +``` +invalidImport.tsx:26:12 lint/correctness/noRenderReturnValue ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Do not depend on the value returned by the function ReactDOM.render(). + + 24 │ lorem = customRender(
, document.body); + 25 │ function render2() { + > 26 │ return customRender(
, document.body) + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 27 │ } + 28 │ + + i The returned value is legacy and future versions of react might return that value asynchronously. + Check the React documentation for more information. + + +``` + + diff --git a/crates/rome_js_analyze/tests/specs/correctness/noRenderReturnValue/validGlobal.tsx b/crates/rome_js_analyze/tests/specs/correctness/noRenderReturnValue/validGlobal.tsx new file mode 100644 index 00000000000..8a9cf47c719 --- /dev/null +++ b/crates/rome_js_analyze/tests/specs/correctness/noRenderReturnValue/validGlobal.tsx @@ -0,0 +1,20 @@ +ReactDOM.render(
, document.body); +function render1() { + ReactDOM.render(
, document.body); +} +const render2 = () => { + ReactDOM.render(
, document.body); +} + +const a = render(
, document.body); +const foo = bar && render(
, document.body); +const foo = bar ? render(
, document.body) : null +const foo = () => render(
, document.body); +const foo = { + react: render(
, document.body) +}; +let lorem; +lorem = render(
, document.body); +function render3() { + return render(
, document.body) +} diff --git a/crates/rome_js_analyze/tests/specs/correctness/noRenderReturnValue/validGlobal.tsx.snap b/crates/rome_js_analyze/tests/specs/correctness/noRenderReturnValue/validGlobal.tsx.snap new file mode 100644 index 00000000000..02b17f72fde --- /dev/null +++ b/crates/rome_js_analyze/tests/specs/correctness/noRenderReturnValue/validGlobal.tsx.snap @@ -0,0 +1,30 @@ +--- +source: crates/rome_js_analyze/tests/spec_tests.rs +expression: validGlobal.tsx +--- +# Input +```js +ReactDOM.render(
, document.body); +function render1() { + ReactDOM.render(
, document.body); +} +const render2 = () => { + ReactDOM.render(
, document.body); +} + +const a = render(
, document.body); +const foo = bar && render(
, document.body); +const foo = bar ? render(
, document.body) : null +const foo = () => render(
, document.body); +const foo = { + react: render(
, document.body) +}; +let lorem; +lorem = render(
, document.body); +function render3() { + return render(
, document.body) +} + +``` + + diff --git a/crates/rome_js_analyze/tests/specs/correctness/noRenderReturnValue/validImport.tsx b/crates/rome_js_analyze/tests/specs/correctness/noRenderReturnValue/validImport.tsx new file mode 100644 index 00000000000..d57c03f81ef --- /dev/null +++ b/crates/rome_js_analyze/tests/specs/correctness/noRenderReturnValue/validImport.tsx @@ -0,0 +1,17 @@ +import ReactDOM, { render } from "react-dom"; + +ReactDOM.render(
, document.body); +function render1() { + ReactDOM.render(
, document.body); +} +const render2 = () => { + ReactDOM.render(
, document.body); +} + +render(
, document.body); +function render1() { + render(
, document.body); +} +const render2 = () => { + render(
, document.body); +} diff --git a/crates/rome_js_analyze/tests/specs/correctness/noRenderReturnValue/validImport.tsx.snap b/crates/rome_js_analyze/tests/specs/correctness/noRenderReturnValue/validImport.tsx.snap new file mode 100644 index 00000000000..c7cb1a19ca1 --- /dev/null +++ b/crates/rome_js_analyze/tests/specs/correctness/noRenderReturnValue/validImport.tsx.snap @@ -0,0 +1,27 @@ +--- +source: crates/rome_js_analyze/tests/spec_tests.rs +expression: validImport.tsx +--- +# Input +```js +import ReactDOM, { render } from "react-dom"; + +ReactDOM.render(
, document.body); +function render1() { + ReactDOM.render(
, document.body); +} +const render2 = () => { + ReactDOM.render(
, document.body); +} + +render(
, document.body); +function render1() { + render(
, document.body); +} +const render2 = () => { + render(
, document.body); +} + +``` + + diff --git a/crates/rome_js_analyze/tests/specs/correctness/noRenderReturnValue/validLocal.tsx b/crates/rome_js_analyze/tests/specs/correctness/noRenderReturnValue/validLocal.tsx new file mode 100644 index 00000000000..7f6b0ec244c --- /dev/null +++ b/crates/rome_js_analyze/tests/specs/correctness/noRenderReturnValue/validLocal.tsx @@ -0,0 +1,28 @@ +function render() { } +const ReactDOM = { render }; + +const a = ReactDOM.render(
, document.body); +const foo = bar && ReactDOM.render(
, document.body); +const foo = bar ? ReactDOM.render(
, document.body) : null +const foo = () => ReactDOM.render(
, document.body); +const foo = { + react: ReactDOM.render(
, document.body) +}; +let lorem; +lorem = ReactDOM.render(
, document.body); +function render1() { + return ReactDOM.render(
, document.body) +} + +const a = render(
, document.body); +const foo = bar && render(
, document.body); +const foo = bar ? render(
, document.body) : null +const foo = () => render(
, document.body); +const foo = { + react: render(
, document.body) +}; +let lorem; +lorem = render(
, document.body); +function render1() { + return render(
, document.body) +} diff --git a/crates/rome_js_analyze/tests/specs/correctness/noRenderReturnValue/validLocal.tsx.snap b/crates/rome_js_analyze/tests/specs/correctness/noRenderReturnValue/validLocal.tsx.snap new file mode 100644 index 00000000000..0c1915009de --- /dev/null +++ b/crates/rome_js_analyze/tests/specs/correctness/noRenderReturnValue/validLocal.tsx.snap @@ -0,0 +1,38 @@ +--- +source: crates/rome_js_analyze/tests/spec_tests.rs +expression: validLocal.tsx +--- +# Input +```js +function render() { } +const ReactDOM = { render }; + +const a = ReactDOM.render(
, document.body); +const foo = bar && ReactDOM.render(
, document.body); +const foo = bar ? ReactDOM.render(
, document.body) : null +const foo = () => ReactDOM.render(
, document.body); +const foo = { + react: ReactDOM.render(
, document.body) +}; +let lorem; +lorem = ReactDOM.render(
, document.body); +function render1() { + return ReactDOM.render(
, document.body) +} + +const a = render(
, document.body); +const foo = bar && render(
, document.body); +const foo = bar ? render(
, document.body) : null +const foo = () => render(
, document.body); +const foo = { + react: render(
, document.body) +}; +let lorem; +lorem = render(
, document.body); +function render1() { + return render(
, document.body) +} + +``` + +