From 9f1d0f1b093b027420be6fd69a2ae5078bc36d63 Mon Sep 17 00:00:00 2001 From: nekosaur Date: Mon, 7 Oct 2024 17:58:39 +0200 Subject: [PATCH 1/5] feat(linter): implement `react/style-prop-object` --- crates/oxc_linter/src/rules.rs | 2 + .../src/rules/react/style_prop_object.rs | 428 ++++++++++++++++++ .../src/snapshots/style_prop_object.snap | 64 +++ 3 files changed, 494 insertions(+) create mode 100644 crates/oxc_linter/src/rules/react/style_prop_object.rs create mode 100644 crates/oxc_linter/src/snapshots/style_prop_object.snap diff --git a/crates/oxc_linter/src/rules.rs b/crates/oxc_linter/src/rules.rs index a0672199f564d..48bca60a168f9 100644 --- a/crates/oxc_linter/src/rules.rs +++ b/crates/oxc_linter/src/rules.rs @@ -258,6 +258,7 @@ mod react { pub mod require_render_return; pub mod rules_of_hooks; pub mod self_closing_comp; + pub mod style_prop_object; pub mod void_dom_elements_no_children; } @@ -794,6 +795,7 @@ oxc_macros::declare_all_lint_rules! { react::require_render_return, react::rules_of_hooks, react::self_closing_comp, + react::style_prop_object, react::void_dom_elements_no_children, react_perf::jsx_no_jsx_as_prop, react_perf::jsx_no_new_array_as_prop, diff --git a/crates/oxc_linter/src/rules/react/style_prop_object.rs b/crates/oxc_linter/src/rules/react/style_prop_object.rs new file mode 100644 index 0000000000000..45b7d4fb2b194 --- /dev/null +++ b/crates/oxc_linter/src/rules/react/style_prop_object.rs @@ -0,0 +1,428 @@ +use oxc_ast::{ + ast::{ + Argument, Expression, JSXAttribute, JSXAttributeItem, JSXAttributeName, JSXAttributeValue, + JSXElementName, ObjectPropertyKind, + }, + AstKind, +}; +use oxc_diagnostics::OxcDiagnostic; +use oxc_macros::declare_oxc_lint; +use oxc_span::Span; + +use crate::{ + ast_util::get_declaration_of_variable, + context::{ContextHost, LintContext}, + rule::Rule, + utils::is_create_element_call, + AstNode, +}; + +fn style_prop_object_diagnostic(span: Span) -> OxcDiagnostic { + OxcDiagnostic::warn("Style prop value must be an object") + .with_help("Make sure the 'style' prop value is an object") + .with_label(span) +} + +#[derive(Debug, Default, Clone)] +pub struct StylePropObject(Box); + +#[derive(Debug, Default, Clone)] +pub struct StylePropObjectConfig { + allow: Vec, +} + +impl std::ops::Deref for StylePropObject { + type Target = StylePropObjectConfig; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +declare_oxc_lint!( + /// ### What it does + /// Require that the value of the prop style be an object or a variable that is an object. + /// + /// ### Examples + /// + /// Examples of **incorrect** code for this rule: + /// ```jsx + ///
+ ///
+ /// + /// const styles = true; + ///
+ /// + /// React.createElement("div", { style: "color: 'red'" }); + /// React.createElement("div", { style: true }); + /// React.createElement("Hello", { style: true }); + /// const styles = true; + /// React.createElement("div", { style: styles }); + /// ``` + /// + /// Examples of **correct** code for this rule: + /// ```jsx + ///
+ /// + /// const styles = { color: "red" }; + ///
+ /// + /// React.createElement("div", { style: { color: 'red' }}); + /// React.createElement("Hello", { style: { color: 'red' }}); + /// const styles = { height: '100px' }; + /// React.createElement("div", { style: styles }); + /// ``` + StylePropObject, + suspicious +); + +fn is_invalid_expression(expression: Option<&Expression>, ctx: &LintContext<'_>) -> bool { + let Some(expression) = expression else { + return false; + }; + + match expression { + Expression::StringLiteral(_) | Expression::BooleanLiteral(_) => true, + Expression::Identifier(ident) => { + let Some(node) = get_declaration_of_variable(ident, ctx) else { + return false; + }; + + let AstKind::VariableDeclarator(var_decl) = node.kind() else { + return false; + }; + + return is_invalid_expression(var_decl.init.as_ref(), ctx); + } + _ => false, + } +} + +fn is_invalid_style_attribute(attribute: &JSXAttribute, ctx: &LintContext<'_>) -> bool { + let JSXAttributeName::Identifier(attr_ident) = &attribute.name else { + return false; + }; + + if attr_ident.name == "style" { + if let Some(attr_value) = &attribute.value { + return match attr_value { + JSXAttributeValue::StringLiteral(_) => true, + JSXAttributeValue::ExpressionContainer(container) => { + return is_invalid_expression(container.expression.as_expression(), ctx); + } + _ => false, + }; + } + } + + false +} + +impl Rule for StylePropObject { + fn from_configuration(value: serde_json::Value) -> Self { + Self(Box::new(StylePropObjectConfig { + allow: value + .get(0) + .and_then(|v| v.get("allow")) + .and_then(serde_json::Value::as_array) + .map(|v| { + v.iter() + .filter_map(serde_json::Value::as_str) + .map(ToString::to_string) + .collect() + }) + .unwrap_or_default(), + })) + } + + fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { + match node.kind() { + AstKind::JSXElement(jsx_elem) => { + let name = match &jsx_elem.opening_element.name { + JSXElementName::Identifier(id) => id.name.as_str(), + JSXElementName::IdentifierReference(id) => id.name.as_str(), + _ => return, + }; + + if self.allow.iter().any(|s| s == name) { + return; + } + + jsx_elem.opening_element.attributes.iter().for_each(|attribute| { + if let JSXAttributeItem::Attribute(attribute) = attribute { + if is_invalid_style_attribute(attribute, ctx) { + ctx.diagnostic(style_prop_object_diagnostic(attribute.span)); + } + } + }); + } + AstKind::CallExpression(call_expr) => { + if !is_create_element_call(call_expr) { + return; + } + + let Some(component) = call_expr.arguments.first() else { + return; + }; + + let Some(expr) = component.as_expression() else { + return; + }; + + let name = match expr { + Expression::StringLiteral(literal) => literal.value.as_str(), + Expression::Identifier(identifier) => identifier.name.as_str(), + _ => return, + }; + + if self.allow.iter().any(|s| s == name) { + return; + } + + let Some(props) = call_expr.arguments.get(1) else { + return; + }; + + let Argument::ObjectExpression(obj_expr) = props else { + return; + }; + + for prop in &obj_expr.properties { + if let ObjectPropertyKind::ObjectProperty(obj_prop) = prop { + if let Some(prop_name) = obj_prop.key.static_name() { + if prop_name == "style" + && is_invalid_expression(Some(&obj_prop.value), ctx) + { + ctx.diagnostic(style_prop_object_diagnostic(obj_prop.span)); + } + } + } + } + } + _ => {} + } + } + + fn should_run(&self, ctx: &ContextHost) -> bool { + ctx.source_type().is_jsx() + } +} + +#[test] +fn test() { + use crate::tester::Tester; + + let pass = vec![ + (r#"
"#, None), + (r#""#, None), + ( + r#" + function redDiv() { + const styles = { color: "red" }; + return
; + } + "#, + None, + ), + ( + r#" + function redDiv() { + const styles = { color: "red" }; + return ; + } + "#, + None, + ), + ( + r#" + const styles = { color: "red" }; + function redDiv() { + return
; + } + "#, + None, + ), + ( + r" + function redDiv(props) { + return
; + } + ", + None, + ), + ( + r" + import styles from './styles'; + function redDiv() { + return
; + } + ", + None, + ), + ( + r" + import mystyles from './styles'; + const styles = Object.assign({ color: 'red' }, mystyles); + function redDiv() { + return
; + } + ", + None, + ), + ( + r#" + const otherProps = { style: { color: "red" } }; + const { a, b, ...props } = otherProps; +
+ "#, + None, + ), + ( + r#" + const styles = Object.assign({ color: 'red' }, mystyles); + React.createElement("div", { style: styles }); + "#, + None, + ), + (r"
", None), + ( + r" + React.createElement(MyCustomElem, { + [style]: true + }, 'My custom Elem') + ", + None, + ), + ( + r" + let style; +
+ ", + None, + ), + ( + r" + let style = null; +
+ ", + None, + ), + ( + r" + let style = undefined; +
+ ", + None, + ), + ( + r" + const otherProps = { style: undefined }; + const { a, b, ...props } = otherProps; +
+ ", + None, + ), + ( + r#" + React.createElement("div", { + style: undefined + }) + "#, + None, + ), + ( + r#" + let style; + React.createElement("div", { + style + }) + "#, + None, + ), + ("
", None), + ( + r" + const props = { style: null }; +
+ ", + None, + ), + ( + r" + const otherProps = { style: null }; + const { a, b, ...props } = otherProps; +
+ ", + None, + ), + ( + r#" + React.createElement("div", { + style: null + }) + "#, + None, + ), + ( + r" + const MyComponent = (props) => { + React.createElement(MyCustomElem, { + ...props + }); + }; + ", + None, + ), + ( + r#""#, + Some(serde_json::json!([{ "allow": ["MyComponent"] }])), + ), + ( + r#"React.createElement(MyComponent, { style: "mySpecialStyle" })"#, + Some(serde_json::json!([{ "allow": ["MyComponent"] }])), + ), + ]; + + let fail = vec![ + (r#"
"#, None), + (r#""#, None), + (r"
", None), + ( + r#" + const styles = 'color: "red"'; + function redDiv2() { + return
; + } + "#, + None, + ), + ( + r#" + const styles = 'color: "blue"'; + function redDiv2() { + return ; + } + "#, + None, + ), + ( + r" + const styles = true; + function redDiv() { + return
; + } + ", + None, + ), + ( + r#""#, + Some(serde_json::json!([{ "allow": ["MyOtherComponent"] }])), + ), + ( + r#"React.createElement(MyComponent2, { style: "mySpecialStyle" })"#, + Some(serde_json::json!([{ "allow": ["MyOtherComponent"] }])), + ), + ]; + + Tester::new(StylePropObject::NAME, pass, fail).test_and_snapshot(); +} diff --git a/crates/oxc_linter/src/snapshots/style_prop_object.snap b/crates/oxc_linter/src/snapshots/style_prop_object.snap new file mode 100644 index 0000000000000..20579eb585357 --- /dev/null +++ b/crates/oxc_linter/src/snapshots/style_prop_object.snap @@ -0,0 +1,64 @@ +--- +source: crates/oxc_linter/src/tester.rs +--- + ⚠ eslint-plugin-react(style-prop-object): Style prop value must be an object + ╭─[style_prop_object.tsx:1:6] + 1 │
+ · ──────────────────── + ╰──── + help: Make sure the 'style' prop value is an object + + ⚠ eslint-plugin-react(style-prop-object): Style prop value must be an object + ╭─[style_prop_object.tsx:1:8] + 1 │ + · ────────────────────── + ╰──── + help: Make sure the 'style' prop value is an object + + ⚠ eslint-plugin-react(style-prop-object): Style prop value must be an object + ╭─[style_prop_object.tsx:1:6] + 1 │
+ · ──────────── + ╰──── + help: Make sure the 'style' prop value is an object + + ⚠ eslint-plugin-react(style-prop-object): Style prop value must be an object + ╭─[style_prop_object.tsx:4:29] + 3 │ function redDiv2() { + 4 │ return
; + · ────────────── + 5 │ } + ╰──── + help: Make sure the 'style' prop value is an object + + ⚠ eslint-plugin-react(style-prop-object): Style prop value must be an object + ╭─[style_prop_object.tsx:4:31] + 3 │ function redDiv2() { + 4 │ return ; + · ────────────── + 5 │ } + ╰──── + help: Make sure the 'style' prop value is an object + + ⚠ eslint-plugin-react(style-prop-object): Style prop value must be an object + ╭─[style_prop_object.tsx:4:29] + 3 │ function redDiv() { + 4 │ return
; + · ────────────── + 5 │ } + ╰──── + help: Make sure the 'style' prop value is an object + + ⚠ eslint-plugin-react(style-prop-object): Style prop value must be an object + ╭─[style_prop_object.tsx:1:14] + 1 │ + · ─────────────── + ╰──── + help: Make sure the 'style' prop value is an object + + ⚠ eslint-plugin-react(style-prop-object): Style prop value must be an object + ╭─[style_prop_object.tsx:1:37] + 1 │ React.createElement(MyComponent2, { style: "mySpecialStyle" }) + · ─────────────────────── + ╰──── + help: Make sure the 'style' prop value is an object From d141e3a7b36516cff3a238d74da57508d528178e Mon Sep 17 00:00:00 2001 From: nekosaur Date: Fri, 11 Oct 2024 23:43:38 +0200 Subject: [PATCH 2/5] fix: pr feedback --- .../src/rules/react/style_prop_object.rs | 120 ++++++++++++++---- .../src/snapshots/style_prop_object.snap | 72 +++++++---- 2 files changed, 143 insertions(+), 49 deletions(-) diff --git a/crates/oxc_linter/src/rules/react/style_prop_object.rs b/crates/oxc_linter/src/rules/react/style_prop_object.rs index 45b7d4fb2b194..2b7a95ea63d05 100644 --- a/crates/oxc_linter/src/rules/react/style_prop_object.rs +++ b/crates/oxc_linter/src/rules/react/style_prop_object.rs @@ -1,13 +1,13 @@ use oxc_ast::{ ast::{ Argument, Expression, JSXAttribute, JSXAttributeItem, JSXAttributeName, JSXAttributeValue, - JSXElementName, ObjectPropertyKind, + JSXElementName, ObjectPropertyKind, TSType, }, AstKind, }; use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; -use oxc_span::Span; +use oxc_span::{CompactStr, GetSpan, Span}; use crate::{ ast_util::get_declaration_of_variable, @@ -18,9 +18,7 @@ use crate::{ }; fn style_prop_object_diagnostic(span: Span) -> OxcDiagnostic { - OxcDiagnostic::warn("Style prop value must be an object") - .with_help("Make sure the 'style' prop value is an object") - .with_label(span) + OxcDiagnostic::warn("Style prop value must be an object").with_label(span) } #[derive(Debug, Default, Clone)] @@ -28,7 +26,7 @@ pub struct StylePropObject(Box); #[derive(Debug, Default, Clone)] pub struct StylePropObjectConfig { - allow: Vec, + allow: Vec, } impl std::ops::Deref for StylePropObject { @@ -41,7 +39,10 @@ impl std::ops::Deref for StylePropObject { declare_oxc_lint!( /// ### What it does - /// Require that the value of the prop style be an object or a variable that is an object. + /// Require that the value of the prop `style` be an object or a variable that is an object. + /// + /// ### Why is this bad? + /// The `style` prop expects an object mapping from style properties to values when using JSX. /// /// ### Examples /// @@ -76,13 +77,27 @@ declare_oxc_lint!( suspicious ); +fn is_invalid_type(ty: &TSType) -> bool { + println!("{:?}", ty); + match ty { + TSType::TSNumberKeyword(_) | TSType::TSStringKeyword(_) | TSType::TSBooleanKeyword(_) => { + true + } + TSType::TSUnionType(union) => union.types.iter().any(is_invalid_type), + TSType::TSIntersectionType(intersect) => intersect.types.iter().any(is_invalid_type), + _ => false, + } +} + fn is_invalid_expression(expression: Option<&Expression>, ctx: &LintContext<'_>) -> bool { let Some(expression) = expression else { return false; }; match expression { - Expression::StringLiteral(_) | Expression::BooleanLiteral(_) => true, + Expression::StringLiteral(_) + | Expression::BooleanLiteral(_) + | Expression::TemplateLiteral(_) => true, Expression::Identifier(ident) => { let Some(node) = get_declaration_of_variable(ident, ctx) else { return false; @@ -92,6 +107,10 @@ fn is_invalid_expression(expression: Option<&Expression>, ctx: &LintContext<'_>) return false; }; + if let Some(asd) = var_decl.id.type_annotation.as_ref() { + return is_invalid_type(&asd.type_annotation); + }; + return is_invalid_expression(var_decl.init.as_ref(), ctx); } _ => false, @@ -120,19 +139,21 @@ fn is_invalid_style_attribute(attribute: &JSXAttribute, ctx: &LintContext<'_>) - impl Rule for StylePropObject { fn from_configuration(value: serde_json::Value) -> Self { - Self(Box::new(StylePropObjectConfig { - allow: value - .get(0) - .and_then(|v| v.get("allow")) - .and_then(serde_json::Value::as_array) - .map(|v| { - v.iter() - .filter_map(serde_json::Value::as_str) - .map(ToString::to_string) - .collect() - }) - .unwrap_or_default(), - })) + let mut allow = value + .get(0) + .and_then(|v| v.get("allow")) + .and_then(serde_json::Value::as_array) + .map(|v| { + v.iter() + .filter_map(serde_json::Value::as_str) + .map(CompactStr::from) + .collect::>() + }) + .unwrap_or_default(); + + allow.sort(); + + Self(Box::new(StylePropObjectConfig { allow })) } fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { @@ -151,7 +172,11 @@ impl Rule for StylePropObject { jsx_elem.opening_element.attributes.iter().for_each(|attribute| { if let JSXAttributeItem::Attribute(attribute) = attribute { if is_invalid_style_attribute(attribute, ctx) { - ctx.diagnostic(style_prop_object_diagnostic(attribute.span)); + let Some(value) = &attribute.value else { + return; + }; + + ctx.diagnostic(style_prop_object_diagnostic(value.span())); } } }); @@ -175,7 +200,7 @@ impl Rule for StylePropObject { _ => return, }; - if self.allow.iter().any(|s| s == name) { + if self.allow.binary_search(&name.into()).is_ok() { return; } @@ -193,7 +218,7 @@ impl Rule for StylePropObject { if prop_name == "style" && is_invalid_expression(Some(&obj_prop.value), ctx) { - ctx.diagnostic(style_prop_object_diagnostic(obj_prop.span)); + ctx.diagnostic(style_prop_object_diagnostic(obj_prop.value.span())); } } } @@ -213,7 +238,8 @@ fn test() { use crate::tester::Tester; let pass = vec![ - (r#"
"#, None), + (r#"
"#, None), + (r#"
"#, None), (r#""#, None), ( r#" @@ -381,12 +407,35 @@ fn test() { r#"React.createElement(MyComponent, { style: "mySpecialStyle" })"#, Some(serde_json::json!([{ "allow": ["MyComponent"] }])), ), + ( + r" + let styles: object | undefined + return
+ ", + None, + ), + ( + r" + let styles: CSSProperties | undefined + return
+ ", + None, + ), ]; let fail = vec![ (r#"
"#, None), (r#""#, None), (r"
", None), + ( + r#" + const styles = `color: "red"`; + function redDiv2() { + return
; + } + "#, + None, + ), ( r#" const styles = 'color: "red"'; @@ -422,6 +471,27 @@ fn test() { r#"React.createElement(MyComponent2, { style: "mySpecialStyle" })"#, Some(serde_json::json!([{ "allow": ["MyOtherComponent"] }])), ), + ( + r" + let styles: string | undefined + return
+ ", + None, + ), + ( + r" + let styles: number | undefined + return
+ ", + None, + ), + ( + r" + let styles: boolean | undefined + return
+ ", + None, + ), ]; Tester::new(StylePropObject::NAME, pass, fail).test_and_snapshot(); diff --git a/crates/oxc_linter/src/snapshots/style_prop_object.snap b/crates/oxc_linter/src/snapshots/style_prop_object.snap index 20579eb585357..9b8f2ab0d6312 100644 --- a/crates/oxc_linter/src/snapshots/style_prop_object.snap +++ b/crates/oxc_linter/src/snapshots/style_prop_object.snap @@ -2,63 +2,87 @@ source: crates/oxc_linter/src/tester.rs --- ⚠ eslint-plugin-react(style-prop-object): Style prop value must be an object - ╭─[style_prop_object.tsx:1:6] + ╭─[style_prop_object.tsx:1:12] 1 │
- · ──────────────────── + · ────────────── ╰──── - help: Make sure the 'style' prop value is an object ⚠ eslint-plugin-react(style-prop-object): Style prop value must be an object - ╭─[style_prop_object.tsx:1:8] + ╭─[style_prop_object.tsx:1:14] 1 │ - · ────────────────────── + · ──────────────── ╰──── - help: Make sure the 'style' prop value is an object ⚠ eslint-plugin-react(style-prop-object): Style prop value must be an object - ╭─[style_prop_object.tsx:1:6] + ╭─[style_prop_object.tsx:1:12] 1 │
- · ──────────── + · ────── ╰──── - help: Make sure the 'style' prop value is an object ⚠ eslint-plugin-react(style-prop-object): Style prop value must be an object - ╭─[style_prop_object.tsx:4:29] + ╭─[style_prop_object.tsx:4:35] 3 │ function redDiv2() { 4 │ return
; - · ────────────── + · ──────── 5 │ } ╰──── - help: Make sure the 'style' prop value is an object ⚠ eslint-plugin-react(style-prop-object): Style prop value must be an object - ╭─[style_prop_object.tsx:4:31] + ╭─[style_prop_object.tsx:4:35] + 3 │ function redDiv2() { + 4 │ return
; + · ──────── + 5 │ } + ╰──── + + ⚠ eslint-plugin-react(style-prop-object): Style prop value must be an object + ╭─[style_prop_object.tsx:4:37] 3 │ function redDiv2() { 4 │ return ; - · ────────────── + · ──────── 5 │ } ╰──── - help: Make sure the 'style' prop value is an object ⚠ eslint-plugin-react(style-prop-object): Style prop value must be an object - ╭─[style_prop_object.tsx:4:29] + ╭─[style_prop_object.tsx:4:35] 3 │ function redDiv() { 4 │ return
; - · ────────────── + · ──────── 5 │ } ╰──── - help: Make sure the 'style' prop value is an object ⚠ eslint-plugin-react(style-prop-object): Style prop value must be an object - ╭─[style_prop_object.tsx:1:14] + ╭─[style_prop_object.tsx:1:20] 1 │ - · ─────────────── + · ───────── ╰──── - help: Make sure the 'style' prop value is an object ⚠ eslint-plugin-react(style-prop-object): Style prop value must be an object - ╭─[style_prop_object.tsx:1:37] + ╭─[style_prop_object.tsx:1:44] 1 │ React.createElement(MyComponent2, { style: "mySpecialStyle" }) - · ─────────────────────── + · ──────────────── + ╰──── + + ⚠ eslint-plugin-react(style-prop-object): Style prop value must be an object + ╭─[style_prop_object.tsx:3:31] + 2 │ let styles: string | undefined + 3 │ return
+ · ──────── + 4 │ + ╰──── + + ⚠ eslint-plugin-react(style-prop-object): Style prop value must be an object + ╭─[style_prop_object.tsx:3:31] + 2 │ let styles: number | undefined + 3 │ return
+ · ──────── + 4 │ + ╰──── + + ⚠ eslint-plugin-react(style-prop-object): Style prop value must be an object + ╭─[style_prop_object.tsx:3:31] + 2 │ let styles: boolean | undefined + 3 │ return
+ · ──────── + 4 │ ╰──── - help: Make sure the 'style' prop value is an object From 4734a282799513f243c236d9c824c60bb382132b Mon Sep 17 00:00:00 2001 From: nekosaur Date: Mon, 14 Oct 2024 21:49:30 +0200 Subject: [PATCH 3/5] fix: remove println --- crates/oxc_linter/src/rules/react/style_prop_object.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/oxc_linter/src/rules/react/style_prop_object.rs b/crates/oxc_linter/src/rules/react/style_prop_object.rs index 2b7a95ea63d05..405bcfd74d0bc 100644 --- a/crates/oxc_linter/src/rules/react/style_prop_object.rs +++ b/crates/oxc_linter/src/rules/react/style_prop_object.rs @@ -78,7 +78,6 @@ declare_oxc_lint!( ); fn is_invalid_type(ty: &TSType) -> bool { - println!("{:?}", ty); match ty { TSType::TSNumberKeyword(_) | TSType::TSStringKeyword(_) | TSType::TSBooleanKeyword(_) => { true From ecb2e8941c222a28798b7cb540aeeec3284128a3 Mon Sep 17 00:00:00 2001 From: Don Isaac Date: Sun, 27 Oct 2024 22:41:31 -0400 Subject: [PATCH 4/5] Update crates/oxc_linter/src/rules/react/style_prop_object.rs --- crates/oxc_linter/src/rules/react/style_prop_object.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/oxc_linter/src/rules/react/style_prop_object.rs b/crates/oxc_linter/src/rules/react/style_prop_object.rs index 405bcfd74d0bc..0f7f501641c79 100644 --- a/crates/oxc_linter/src/rules/react/style_prop_object.rs +++ b/crates/oxc_linter/src/rules/react/style_prop_object.rs @@ -88,7 +88,7 @@ fn is_invalid_type(ty: &TSType) -> bool { } } -fn is_invalid_expression(expression: Option<&Expression>, ctx: &LintContext<'_>) -> bool { +fn is_invalid_expression<'a>(expression: Option<&Expression<'a>>, ctx: &LintContext<'a>) -> bool { let Some(expression) = expression else { return false; }; From 536f250a9dfba25dde28df38d78d0c12ae9c45e7 Mon Sep 17 00:00:00 2001 From: Don Isaac Date: Sun, 27 Oct 2024 22:43:33 -0400 Subject: [PATCH 5/5] Update crates/oxc_linter/src/rules/react/style_prop_object.rs --- crates/oxc_linter/src/rules/react/style_prop_object.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/oxc_linter/src/rules/react/style_prop_object.rs b/crates/oxc_linter/src/rules/react/style_prop_object.rs index 0f7f501641c79..d0d6b1c0dc0b1 100644 --- a/crates/oxc_linter/src/rules/react/style_prop_object.rs +++ b/crates/oxc_linter/src/rules/react/style_prop_object.rs @@ -116,7 +116,7 @@ fn is_invalid_expression<'a>(expression: Option<&Expression<'a>>, ctx: &LintCont } } -fn is_invalid_style_attribute(attribute: &JSXAttribute, ctx: &LintContext<'_>) -> bool { +fn is_invalid_style_attribute<'a>(attribute: &JSXAttribute<'a>, ctx: &LintContext<'a>) -> bool { let JSXAttributeName::Identifier(attr_ident) = &attribute.name else { return false; };