diff --git a/crates/oxc_ast/src/ast_impl/js.rs b/crates/oxc_ast/src/ast_impl/js.rs index fa243d2d5adb9..3da6d3a0daffa 100644 --- a/crates/oxc_ast/src/ast_impl/js.rs +++ b/crates/oxc_ast/src/ast_impl/js.rs @@ -459,9 +459,7 @@ impl<'a> PropertyKey<'a> { Self::NumericLiteral(lit) => Some(Cow::Owned(lit.value.to_string())), Self::BigIntLiteral(lit) => Some(Cow::Borrowed(lit.value.as_str())), Self::NullLiteral(_) => Some(Cow::Borrowed("null")), - Self::TemplateLiteral(lit) => { - lit.expressions.is_empty().then(|| lit.quasi()).flatten().map(Into::into) - } + Self::TemplateLiteral(lit) => lit.single_quasi().map(Into::into), _ => None, } } @@ -548,7 +546,7 @@ impl<'a> TemplateLiteral<'a> { } /// Get single quasi from `template` - pub fn quasi(&self) -> Option> { + pub fn single_quasi(&self) -> Option> { if self.is_no_substitution_template() { self.quasis[0].value.cooked } else { None } } } diff --git a/crates/oxc_ast/src/ast_impl/ts.rs b/crates/oxc_ast/src/ast_impl/ts.rs index 94b054db4363d..46ac6eca6b390 100644 --- a/crates/oxc_ast/src/ast_impl/ts.rs +++ b/crates/oxc_ast/src/ast_impl/ts.rs @@ -19,7 +19,7 @@ impl<'a> TSEnumMemberName<'a> { Self::Identifier(ident) => ident.name, Self::String(lit) | Self::ComputedString(lit) => lit.value, Self::ComputedTemplateString(template) => template - .quasi() + .single_quasi() .expect("`TSEnumMemberName::TemplateString` should have no substitution and at least one quasi"), } } diff --git a/crates/oxc_ast/src/ast_kind_impl.rs b/crates/oxc_ast/src/ast_kind_impl.rs index 5f59c3f5d75c5..1c79e5d39b5ad 100644 --- a/crates/oxc_ast/src/ast_kind_impl.rs +++ b/crates/oxc_ast/src/ast_kind_impl.rs @@ -251,7 +251,7 @@ impl AstKind<'_> { Self::RegExpLiteral(r) => format!("RegExpLiteral({})", r.regex).into(), Self::TemplateLiteral(t) => format!( "TemplateLiteral({})", - t.quasi().map_or_else(|| "None".into(), |q| format!("Some({q})")) + t.single_quasi().map_or_else(|| "None".into(), |q| format!("Some({q})")) ) .into(), Self::TemplateElement(_) => "TemplateElement".into(), diff --git a/crates/oxc_ecmascript/src/side_effects/may_have_side_effects.rs b/crates/oxc_ecmascript/src/side_effects/may_have_side_effects.rs index 5ad8035eced6b..b3c96a976ee76 100644 --- a/crates/oxc_ecmascript/src/side_effects/may_have_side_effects.rs +++ b/crates/oxc_ecmascript/src/side_effects/may_have_side_effects.rs @@ -417,7 +417,7 @@ impl<'a> MayHaveSideEffects<'a> for ComputedMemberExpression<'a> { Expression::StringLiteral(s) => { property_access_may_have_side_effects(&self.object, &s.value, ctx) } - Expression::TemplateLiteral(t) => t.quasi().is_some_and(|quasi| { + Expression::TemplateLiteral(t) => t.single_quasi().is_some_and(|quasi| { property_access_may_have_side_effects(&self.object, &quasi, ctx) }), Expression::NumericLiteral(n) => !n.value.to_integer_index().is_some_and(|n| { diff --git a/crates/oxc_ecmascript/src/to_primitive.rs b/crates/oxc_ecmascript/src/to_primitive.rs index 94cab7aa16815..d88f31dc56c69 100644 --- a/crates/oxc_ecmascript/src/to_primitive.rs +++ b/crates/oxc_ecmascript/src/to_primitive.rs @@ -92,9 +92,9 @@ pub fn maybe_object_with_to_primitive_related_properties_overridden( PropertyKey::StringLiteral(str) => { matches!(str.value.as_str(), "toString" | "valueOf") } - PropertyKey::TemplateLiteral(temp) => { - temp.quasi().is_some_and(|val| matches!(val.as_str(), "toString" | "valueOf")) - } + PropertyKey::TemplateLiteral(temp) => temp + .single_quasi() + .is_some_and(|val| matches!(val.as_str(), "toString" | "valueOf")), _ => true, }, ObjectPropertyKind::SpreadProperty(e) => match &e.argument { diff --git a/crates/oxc_linter/src/ast_util.rs b/crates/oxc_linter/src/ast_util.rs index 5bb14de33eb5b..8a884ae34929c 100644 --- a/crates/oxc_linter/src/ast_util.rs +++ b/crates/oxc_linter/src/ast_util.rs @@ -308,7 +308,7 @@ pub fn extract_regex_flags<'a>( } let flag_arg = match &args[1] { Argument::StringLiteral(flag_arg) => flag_arg.value, - Argument::TemplateLiteral(template) => template.quasi()?, + Argument::TemplateLiteral(template) => template.single_quasi()?, _ => return None, }; let mut flags = RegExpFlags::empty(); diff --git a/crates/oxc_linter/src/rules/eslint/valid_typeof.rs b/crates/oxc_linter/src/rules/eslint/valid_typeof.rs index ecf1c8c347dc8..562d15c15f136 100644 --- a/crates/oxc_linter/src/rules/eslint/valid_typeof.rs +++ b/crates/oxc_linter/src/rules/eslint/valid_typeof.rs @@ -124,7 +124,7 @@ impl Rule for ValidTypeof { } if let Expression::TemplateLiteral(template) = sibling { - if let Some(quasi) = template.quasi() { + if let Some(quasi) = template.single_quasi() { if !VALID_TYPES.contains(&quasi.as_str()) { ctx.diagnostic(invalid_value(None, sibling.span())); } diff --git a/crates/oxc_linter/src/rules/jest/no_identical_title.rs b/crates/oxc_linter/src/rules/jest/no_identical_title.rs index f880f2eda46d2..dc06b1193e02d 100644 --- a/crates/oxc_linter/src/rules/jest/no_identical_title.rs +++ b/crates/oxc_linter/src/rules/jest/no_identical_title.rs @@ -149,9 +149,9 @@ fn filter_and_process_jest_result<'a>( Some(Argument::StringLiteral(string_lit)) => { Some((string_lit.span, &string_lit.value, kind, parent_id)) } - Some(Argument::TemplateLiteral(template_lit)) => { - template_lit.quasi().map(|quasi| (template_lit.span, quasi.as_str(), kind, parent_id)) - } + Some(Argument::TemplateLiteral(template_lit)) => template_lit + .single_quasi() + .map(|quasi| (template_lit.span, quasi.as_str(), kind, parent_id)), _ => None, } } diff --git a/crates/oxc_linter/src/rules/jest/prefer_lowercase_title/mod.rs b/crates/oxc_linter/src/rules/jest/prefer_lowercase_title/mod.rs index d7c8e4d682027..7bfa777e90044 100644 --- a/crates/oxc_linter/src/rules/jest/prefer_lowercase_title/mod.rs +++ b/crates/oxc_linter/src/rules/jest/prefer_lowercase_title/mod.rs @@ -238,7 +238,7 @@ impl Rule for PreferLowercaseTitle { if let Argument::StringLiteral(string_expr) = arg { self.lint_string(ctx, string_expr.value.as_str(), string_expr.span); } else if let Argument::TemplateLiteral(template_expr) = arg { - let Some(template_string) = template_expr.quasi() else { + let Some(template_string) = template_expr.single_quasi() else { return; }; self.lint_string(ctx, template_string.as_str(), template_expr.span); diff --git a/crates/oxc_linter/src/rules/jest/valid_title.rs b/crates/oxc_linter/src/rules/jest/valid_title.rs index a145e2420fb51..720cb02803336 100644 --- a/crates/oxc_linter/src/rules/jest/valid_title.rs +++ b/crates/oxc_linter/src/rules/jest/valid_title.rs @@ -180,7 +180,7 @@ impl ValidTitle { ); } Argument::TemplateLiteral(template_literal) => { - if let Some(quasi) = template_literal.quasi() { + if let Some(quasi) = template_literal.single_quasi() { validate_title( quasi.as_str(), template_literal.span, diff --git a/crates/oxc_linter/src/rules/jsx_a11y/anchor_is_valid.rs b/crates/oxc_linter/src/rules/jsx_a11y/anchor_is_valid.rs index f24ab2607b535..2563c7e8fd86a 100644 --- a/crates/oxc_linter/src/rules/jsx_a11y/anchor_is_valid.rs +++ b/crates/oxc_linter/src/rules/jsx_a11y/anchor_is_valid.rs @@ -188,7 +188,7 @@ impl AnchorIsValid { return false; } - let Some(quasi) = temp_lit.quasi() else { + let Some(quasi) = temp_lit.single_quasi() else { return false; }; self.is_invalid_href(&quasi) diff --git a/crates/oxc_linter/src/rules/react/button_has_type.rs b/crates/oxc_linter/src/rules/react/button_has_type.rs index e8b9616186ae1..a4f5d382213a4 100644 --- a/crates/oxc_linter/src/rules/react/button_has_type.rs +++ b/crates/oxc_linter/src/rules/react/button_has_type.rs @@ -181,7 +181,7 @@ impl ButtonHasType { self.is_valid_button_type_prop_string_literal(str.value.as_str()) } Expression::TemplateLiteral(template_literal) => template_literal - .quasi() + .single_quasi() .is_some_and(|quasi| self.is_valid_button_type_prop_string_literal(quasi.as_str())), Expression::ConditionalExpression(conditional_expr) => { self.is_valid_button_type_prop_expression(&conditional_expr.consequent) diff --git a/crates/oxc_linter/src/rules/react/jsx_curly_brace_presence.rs b/crates/oxc_linter/src/rules/react/jsx_curly_brace_presence.rs index a658f3c9a465a..449e6e9c4ddbc 100644 --- a/crates/oxc_linter/src/rules/react/jsx_curly_brace_presence.rs +++ b/crates/oxc_linter/src/rules/react/jsx_curly_brace_presence.rs @@ -463,7 +463,7 @@ impl JsxCurlyBracePresence { } Expression::TemplateLiteral(template) => { if allowed.is_never() - && let Some(string) = template.quasi() + && let Some(string) = template.single_quasi() { if contains_quote_characters(string.as_str()) || is_allowed_string_like( @@ -803,7 +803,7 @@ fn test() { ( r#" import React from "react"; - + const Component = () => { return {"/*"}; }; diff --git a/crates/oxc_linter/src/rules/unicorn/no_thenable.rs b/crates/oxc_linter/src/rules/unicorn/no_thenable.rs index 974b92efd6d73..ffb7d5e35d0de 100644 --- a/crates/oxc_linter/src/rules/unicorn/no_thenable.rs +++ b/crates/oxc_linter/src/rules/unicorn/no_thenable.rs @@ -250,7 +250,7 @@ fn check_expression(expr: &Expression, ctx: &LintContext<'_>) -> Option { - lit.quasi().and_then(|quasi| if quasi == "then" { Some(lit.span) } else { None }) + lit.single_quasi().and_then(|quasi| if quasi == "then" { Some(lit.span) } else { None }) } Expression::Identifier(ident) => { let symbols = ctx.scoping(); diff --git a/crates/oxc_linter/src/rules/unicorn/prefer_negative_index.rs b/crates/oxc_linter/src/rules/unicorn/prefer_negative_index.rs index 3a42550e26dd3..4351863560f66 100644 --- a/crates/oxc_linter/src/rules/unicorn/prefer_negative_index.rs +++ b/crates/oxc_linter/src/rules/unicorn/prefer_negative_index.rs @@ -201,7 +201,7 @@ fn is_same_node(left: &Expression, right: &Expression, ctx: &LintContext) -> boo Expression::TemplateLiteral(left_template_lit), Expression::StringLiteral(right_string_lit), ) => { - let Some(template_str) = left_template_lit.quasi() else { + let Some(template_str) = left_template_lit.single_quasi() else { return false; }; @@ -211,7 +211,7 @@ fn is_same_node(left: &Expression, right: &Expression, ctx: &LintContext) -> boo Expression::StringLiteral(left_string_lit), Expression::TemplateLiteral(right_template_lit), ) => { - let Some(template_str) = right_template_lit.quasi() else { + let Some(template_str) = right_template_lit.single_quasi() else { return false; }; diff --git a/crates/oxc_linter/src/utils/express.rs b/crates/oxc_linter/src/utils/express.rs index 5b2162cea5276..5e2fbcac751e1 100644 --- a/crates/oxc_linter/src/utils/express.rs +++ b/crates/oxc_linter/src/utils/express.rs @@ -35,7 +35,7 @@ pub fn as_endpoint_registration<'a, 'n>( Some((Some(path.value), &call.arguments.as_slice()[1..])) } Expression::TemplateLiteral(template) => { - template.quasi().map(|quasi| (Some(quasi), &call.arguments.as_slice()[1..])) + template.single_quasi().map(|quasi| (Some(quasi), &call.arguments.as_slice()[1..])) } _ => Some((None, call.arguments.as_slice())), } diff --git a/crates/oxc_linter/src/utils/jest.rs b/crates/oxc_linter/src/utils/jest.rs index 486f26a45fcad..c7b58cb85c8f1 100644 --- a/crates/oxc_linter/src/utils/jest.rs +++ b/crates/oxc_linter/src/utils/jest.rs @@ -272,7 +272,7 @@ pub fn get_node_name_vec<'a>(expr: &'a Expression<'a>) -> Vec> { chain.push(Cow::Borrowed(&string_literal.value)); } Expression::TemplateLiteral(template_literal) => { - if let Some(quasi) = template_literal.quasi() { + if let Some(quasi) = template_literal.single_quasi() { chain.push(Cow::Borrowed(quasi.as_str())); } } diff --git a/crates/oxc_linter/src/utils/jest/parse_jest_fn.rs b/crates/oxc_linter/src/utils/jest/parse_jest_fn.rs index b19b65b9322bc..2d6be75aeba7c 100644 --- a/crates/oxc_linter/src/utils/jest/parse_jest_fn.rs +++ b/crates/oxc_linter/src/utils/jest/parse_jest_fn.rs @@ -418,7 +418,7 @@ impl<'a> KnownMemberExpressionProperty<'a> { Some(Cow::Borrowed(string_literal.value.as_str())) } Expression::TemplateLiteral(template_literal) => Some(Cow::Borrowed( - template_literal.quasi().expect("get string content").as_str(), + template_literal.single_quasi().expect("get string content").as_str(), )), _ => None, }, diff --git a/crates/oxc_linter/src/utils/unicorn.rs b/crates/oxc_linter/src/utils/unicorn.rs index 35e48d30276bd..4267488408249 100644 --- a/crates/oxc_linter/src/utils/unicorn.rs +++ b/crates/oxc_linter/src/utils/unicorn.rs @@ -181,7 +181,7 @@ pub fn is_same_expression(left: &Expression, right: &Expression, ctx: &LintConte } (Expression::StringLiteral(string_lit), Expression::TemplateLiteral(template_lit)) | (Expression::TemplateLiteral(template_lit), Expression::StringLiteral(string_lit)) => { - return template_lit.quasi().is_some_and(|val| val.as_str() == string_lit.value); + return template_lit.single_quasi().is_some_and(|val| val.as_str() == string_lit.value); } (Expression::TemplateLiteral(left_str), Expression::TemplateLiteral(right_str)) => { return left_str.quasis.content_eq(&right_str.quasis) @@ -303,7 +303,10 @@ pub fn is_same_member_expression( // ex) x[/regex/] === x[`/regex/`] (Expression::TemplateLiteral(template_lit), Expression::RegExpLiteral(regex_lit)) | (Expression::RegExpLiteral(regex_lit), Expression::TemplateLiteral(template_lit)) => { - if !template_lit.quasi().is_some_and(|val| val == regex_lit.raw.as_ref().unwrap()) { + if !template_lit + .single_quasi() + .is_some_and(|val| val == regex_lit.raw.as_ref().unwrap()) + { return false; } } diff --git a/tasks/rulegen/src/main.rs b/tasks/rulegen/src/main.rs index 43a74f06f3e0f..804a5ff71de18 100644 --- a/tasks/rulegen/src/main.rs +++ b/tasks/rulegen/src/main.rs @@ -178,7 +178,7 @@ fn format_tagged_template_expression(tag_expr: &TaggedTemplateExpression) -> Opt } else if tag_expr.tag.is_specific_id("dedent") || tag_expr.tag.is_specific_id("outdent") { tag_expr.quasi.quasis.first().map(|quasi| util::dedent(&quasi.value.raw)) } else { - tag_expr.quasi.quasi().map(|quasi| quasi.to_string()) + tag_expr.quasi.single_quasi().map(|quasi| quasi.to_string()) } } @@ -225,7 +225,7 @@ impl<'a> Visit<'a> for TestCase { format_tagged_template_expression(tag_expr) } Expression::TemplateLiteral(tag_expr) => { - tag_expr.quasi().map(|quasi| quasi.to_string()) + tag_expr.single_quasi().map(|quasi| quasi.to_string()) } // handle code like ["{", "a: 1", "}"].join("\n") Expression::CallExpression(call_expr) => { @@ -266,7 +266,7 @@ impl<'a> Visit<'a> for TestCase { format_tagged_template_expression(tag_expr) } Expression::TemplateLiteral(tag_expr) => { - tag_expr.quasi().map(|quasi| quasi.to_string()) + tag_expr.single_quasi().map(|quasi| quasi.to_string()) } _ => None, } @@ -301,7 +301,7 @@ impl<'a> Visit<'a> for TestCase { } fn visit_template_literal(&mut self, lit: &TemplateLiteral<'a>) { - self.code = Some(lit.quasi().unwrap().to_string()); + self.code = Some(lit.single_quasi().unwrap().to_string()); self.config = None; }