From df7eddd6db646a9811dfb416d0e38225681e67f7 Mon Sep 17 00:00:00 2001 From: rzvxa <3788964+rzvxa@users.noreply.github.com> Date: Wed, 4 Sep 2024 13:55:34 +0000 Subject: [PATCH] refactor(linter): use "parsed pattern" in `no_div_regex` rule. (#5417) Part of #5416, Paves the road for upcoming refactors by adding the `oxc_regular_expression` dependency and a helper method for ease of access. --- Cargo.lock | 1 + crates/oxc_ast/src/ast_impl/literal.rs | 23 +++++++++++++++++ crates/oxc_linter/Cargo.toml | 25 ++++++++++--------- .../src/rules/eslint/no_div_regex.rs | 10 +++++++- 4 files changed, 46 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8c08de8d44a28..542e7f5d36465 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1639,6 +1639,7 @@ dependencies = [ "oxc_index", "oxc_macros", "oxc_parser", + "oxc_regular_expression", "oxc_resolver", "oxc_semantic", "oxc_span", diff --git a/crates/oxc_ast/src/ast_impl/literal.rs b/crates/oxc_ast/src/ast_impl/literal.rs index 1dd5c3f89a751..1b73e7efc2b2b 100644 --- a/crates/oxc_ast/src/ast_impl/literal.rs +++ b/crates/oxc_ast/src/ast_impl/literal.rs @@ -11,6 +11,7 @@ use std::{ }; use oxc_allocator::CloneIn; +use oxc_regular_expression::ast::Pattern; use oxc_span::{cmp::ContentEq, Atom, Span}; use oxc_syntax::number::NumberBase; @@ -137,6 +138,28 @@ impl<'a> RegExpPattern<'a> { Self::Pattern(pat) => pat.span.source_text(source_text), } } + + /// # Panics + /// If `self` is anything but `RegExpPattern::Pattern`. + pub fn require_pattern(&self) -> &Pattern<'a> { + if let Some(it) = self.as_pattern() { + it + } else { + unreachable!( + "Required `{}` to be `{}`", + stringify!(RegExpPattern), + stringify!(Pattern) + ); + } + } + + pub fn as_pattern(&self) -> Option<&Pattern<'a>> { + if let Self::Pattern(it) = self { + Some(it.as_ref()) + } else { + None + } + } } impl<'a> fmt::Display for RegExpPattern<'a> { diff --git a/crates/oxc_linter/Cargo.toml b/crates/oxc_linter/Cargo.toml index 69c2868ef4810..fe4f9b004d5d9 100644 --- a/crates/oxc_linter/Cargo.toml +++ b/crates/oxc_linter/Cargo.toml @@ -20,18 +20,19 @@ workspace = true doctest = false [dependencies] -oxc_allocator = { workspace = true } -oxc_parser = { workspace = true } -oxc_span = { workspace = true, features = ["schemars", "serialize"] } -oxc_ast = { workspace = true } -oxc_cfg = { workspace = true } -oxc_diagnostics = { workspace = true } -oxc_index = { workspace = true } -oxc_macros = { workspace = true } -oxc_semantic = { workspace = true } -oxc_syntax = { workspace = true } -oxc_codegen = { workspace = true } -oxc_resolver = { workspace = true } +oxc_allocator = { workspace = true } +oxc_parser = { workspace = true } +oxc_span = { workspace = true, features = ["schemars", "serialize"] } +oxc_ast = { workspace = true } +oxc_cfg = { workspace = true } +oxc_diagnostics = { workspace = true } +oxc_index = { workspace = true } +oxc_macros = { workspace = true } +oxc_semantic = { workspace = true } +oxc_syntax = { workspace = true } +oxc_codegen = { workspace = true } +oxc_resolver = { workspace = true } +oxc_regular_expression = { workspace = true } rayon = { workspace = true } bitflags = { workspace = true } diff --git a/crates/oxc_linter/src/rules/eslint/no_div_regex.rs b/crates/oxc_linter/src/rules/eslint/no_div_regex.rs index 44f0e7f9d9eef..a4ca3ab52f245 100644 --- a/crates/oxc_linter/src/rules/eslint/no_div_regex.rs +++ b/crates/oxc_linter/src/rules/eslint/no_div_regex.rs @@ -1,6 +1,7 @@ use oxc_ast::AstKind; use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; +use oxc_regular_expression::ast::{CharacterKind, Term}; use oxc_span::Span; use crate::{context::LintContext, rule::Rule, AstNode}; @@ -36,7 +37,14 @@ declare_oxc_lint!( impl Rule for NoDivRegex { fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { if let AstKind::RegExpLiteral(lit) = node.kind() { - if lit.regex.pattern.source_text(ctx.source_text()).starts_with('=') { + let Some(pattern) = lit.regex.pattern.as_pattern() else { return }; + if pattern + .body + .body + .first() + .and_then(|it| it.body.first()) + .is_some_and(|it| matches!(it, Term::Character(ch) if ch.kind == CharacterKind::Symbol && ch.value == '=' as u32)) + { ctx.diagnostic_with_fix(no_div_regex_diagnostic(lit.span), |fixer| { let span = Span::sized(lit.span.start + 1, 1); fixer.replace(span, "[=]")