diff --git a/crates/oxc_linter/src/rules/unicorn/prefer_string_starts_ends_with.rs b/crates/oxc_linter/src/rules/unicorn/prefer_string_starts_ends_with.rs index 0986578567417..359ed4cbc1167 100644 --- a/crates/oxc_linter/src/rules/unicorn/prefer_string_starts_ends_with.rs +++ b/crates/oxc_linter/src/rules/unicorn/prefer_string_starts_ends_with.rs @@ -4,6 +4,7 @@ use oxc_ast::{ }; use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; +use oxc_regular_expression::ast::{BoundaryAssertionKind, Term}; use oxc_span::{GetSpan, Span}; use crate::{ @@ -146,24 +147,33 @@ fn check_regex(regexp_lit: &RegExpLiteral, pattern_text: &str) -> Option 1 { + return None; } + let pattern_terms = alternatives.first().map(|it| &it.body)?; - if pattern_text.ends_with('$') - && is_simple_string(&pattern_text[0..regexp_lit.regex.pattern.len() - 1]) - { - return Some(ErrorKind::EndsWith); + if let Some(Term::BoundaryAssertion(boundary_assert)) = pattern_terms.first() { + if boundary_assert.kind == BoundaryAssertionKind::Start + && pattern_terms.iter().skip(1).all(|term| matches!(term, Term::Character(_))) + { + return Some(ErrorKind::StartsWith); + } } - None -} + if let Some(Term::BoundaryAssertion(boundary_assert)) = pattern_terms.last() { + if boundary_assert.kind == BoundaryAssertionKind::End + && pattern_terms + .iter() + .take(pattern_terms.len() - 1) + .all(|term| matches!(term, Term::Character(_))) + { + return Some(ErrorKind::EndsWith); + } + } -fn is_simple_string(str: &str) -> bool { - str.chars() - .all(|c| !matches!(c, '^' | '$' | '+' | '[' | '{' | '(' | '\\' | '.' | '?' | '*' | '|')) + None } // `/^#/i` => `true` (the `i` flag is useless)