diff --git a/crates/oxc_linter/src/rules/eslint/no_invalid_regexp.rs b/crates/oxc_linter/src/rules/eslint/no_invalid_regexp.rs index d8ca51f31f110..044356c481e36 100644 --- a/crates/oxc_linter/src/rules/eslint/no_invalid_regexp.rs +++ b/crates/oxc_linter/src/rules/eslint/no_invalid_regexp.rs @@ -15,17 +15,28 @@ use crate::{ }; // Use the same prefix with `oxc_regular_expression` crate -fn duplicated_flag_diagnostic(span: Span) -> OxcDiagnostic { - OxcDiagnostic::warn("Invalid regular expression: Duplicated flag").with_label(span) +fn duplicated_flag_diagnostic(span: Span, flag: &str) -> OxcDiagnostic { + OxcDiagnostic::warn("Invalid regular expression: Duplicated flag") + .with_help( + format!("Remove the duplicated '{flag}' flag from the regular expression flags",), + ) + .with_label(span.label(format!("flag '{flag}' already specified"))) } -fn unknown_flag_diagnostic(span: Span) -> OxcDiagnostic { - OxcDiagnostic::warn("Invalid regular expression: Unknown flag").with_label(span) +fn unknown_flag_diagnostic(span: Span, flag: &str) -> OxcDiagnostic { + OxcDiagnostic::warn("Invalid regular expression: Unknown flag") + .with_note("Valid flags are: d (indices), g (global), i (ignore case), m (multiline),\n s (dot all), u (unicode), v (unicode sets), y (sticky)") + .with_label(span.label(format!("flag '{flag}' is not a valid regular expression flag"))) } -fn invalid_unicode_flags_diagnostic(span: Span) -> OxcDiagnostic { +fn invalid_unicode_flags_diagnostic(span: Span, is_u_specified: bool) -> OxcDiagnostic { OxcDiagnostic::warn("Invalid regular expression: `u` and `v` flags should be used alone") - .with_label(span) + .with_help("Specify only one of 'u' or 'v' flags") + .with_label(span.label(if is_u_specified { + "the 'v' flag cannot be used when the 'u' flag is specified" + } else { + "the 'u' flag cannot be used when the 'v' flag is specified" + })) } #[derive(Debug, Default, Clone, Deserialize)] @@ -111,29 +122,37 @@ impl Rule for NoInvalidRegexp { // Invalid combination: u+v if ch == 'u' { if v_flag_found { - return ctx - .diagnostic(invalid_unicode_flags_diagnostic(Span::empty(start))); + return ctx.diagnostic(invalid_unicode_flags_diagnostic( + Span::empty(start), + false, + )); } u_flag_found = true; } if ch == 'v' { if u_flag_found { - return ctx - .diagnostic(invalid_unicode_flags_diagnostic(Span::empty(start))); + return ctx.diagnostic(invalid_unicode_flags_diagnostic( + Span::empty(start), + true, + )); } v_flag_found = true; } // Duplicated: user defined, invalid or valid if !unique_flags.insert(ch) { - return ctx.diagnostic(duplicated_flag_diagnostic(Span::empty(start))); + return ctx.diagnostic(duplicated_flag_diagnostic( + Span::empty(start), + &ch.to_string(), + )); } // Unknown: not valid, not user defined if !(matches!(ch, 'd' | 'g' | 'i' | 'm' | 's' | 'u' | 'v' | 'y') || self.0.allow_constructor_flags.contains(&ch)) { - return ctx.diagnostic(unknown_flag_diagnostic(Span::empty(start))); + return ctx + .diagnostic(unknown_flag_diagnostic(Span::empty(start), &ch.to_string())); } } } diff --git a/crates/oxc_linter/src/snapshots/eslint_no_invalid_regexp.snap b/crates/oxc_linter/src/snapshots/eslint_no_invalid_regexp.snap index 42278f74e1a9e..0ab69c8b072ae 100644 --- a/crates/oxc_linter/src/snapshots/eslint_no_invalid_regexp.snap +++ b/crates/oxc_linter/src/snapshots/eslint_no_invalid_regexp.snap @@ -12,91 +12,130 @@ source: crates/oxc_linter/src/tester.rs ╭─[no_invalid_regexp.tsx:1:14] 1 │ RegExp('.', 'z'); · ▲ + · ╰── flag 'z' is not a valid regular expression flag ╰──── + note: Valid flags are: d (indices), g (global), i (ignore case), m (multiline), + s (dot all), u (unicode), v (unicode sets), y (sticky) ⚠ eslint(no-invalid-regexp): Invalid regular expression: Unknown flag ╭─[no_invalid_regexp.tsx:1:14] 1 │ RegExp('.', 'a'); · ▲ + · ╰── flag 'a' is not a valid regular expression flag ╰──── + note: Valid flags are: d (indices), g (global), i (ignore case), m (multiline), + s (dot all), u (unicode), v (unicode sets), y (sticky) ⚠ eslint(no-invalid-regexp): Invalid regular expression: Unknown flag ╭─[no_invalid_regexp.tsx:1:18] 1 │ new RegExp('.', 'a'); · ▲ + · ╰── flag 'a' is not a valid regular expression flag ╰──── + note: Valid flags are: d (indices), g (global), i (ignore case), m (multiline), + s (dot all), u (unicode), v (unicode sets), y (sticky) ⚠ eslint(no-invalid-regexp): Invalid regular expression: Unknown flag ╭─[no_invalid_regexp.tsx:1:18] 1 │ new RegExp('.', 'z'); · ▲ + · ╰── flag 'z' is not a valid regular expression flag ╰──── + note: Valid flags are: d (indices), g (global), i (ignore case), m (multiline), + s (dot all), u (unicode), v (unicode sets), y (sticky) ⚠ eslint(no-invalid-regexp): Invalid regular expression: Unknown flag ╭─[no_invalid_regexp.tsx:1:14] 1 │ RegExp('.', 'a'); · ▲ + · ╰── flag 'a' is not a valid regular expression flag ╰──── + note: Valid flags are: d (indices), g (global), i (ignore case), m (multiline), + s (dot all), u (unicode), v (unicode sets), y (sticky) ⚠ eslint(no-invalid-regexp): Invalid regular expression: Unknown flag ╭─[no_invalid_regexp.tsx:1:14] 1 │ RegExp('.', 'A'); · ▲ + · ╰── flag 'A' is not a valid regular expression flag ╰──── + note: Valid flags are: d (indices), g (global), i (ignore case), m (multiline), + s (dot all), u (unicode), v (unicode sets), y (sticky) ⚠ eslint(no-invalid-regexp): Invalid regular expression: Unknown flag ╭─[no_invalid_regexp.tsx:1:18] 1 │ new RegExp('.', 'az'); · ▲ + · ╰── flag 'a' is not a valid regular expression flag ╰──── + note: Valid flags are: d (indices), g (global), i (ignore case), m (multiline), + s (dot all), u (unicode), v (unicode sets), y (sticky) ⚠ eslint(no-invalid-regexp): Invalid regular expression: Duplicated flag ╭─[no_invalid_regexp.tsx:1:19] 1 │ new RegExp('.', 'aa'); · ▲ + · ╰── flag 'a' already specified ╰──── + help: Remove the duplicated 'a' flag from the regular expression flags ⚠ eslint(no-invalid-regexp): Invalid regular expression: Duplicated flag ╭─[no_invalid_regexp.tsx:1:19] 1 │ new RegExp('.', 'aa'); · ▲ + · ╰── flag 'a' already specified ╰──── + help: Remove the duplicated 'a' flag from the regular expression flags ⚠ eslint(no-invalid-regexp): Invalid regular expression: Unknown flag ╭─[no_invalid_regexp.tsx:1:19] 1 │ new RegExp('.', 'aA'); · ▲ + · ╰── flag 'A' is not a valid regular expression flag ╰──── + note: Valid flags are: d (indices), g (global), i (ignore case), m (multiline), + s (dot all), u (unicode), v (unicode sets), y (sticky) ⚠ eslint(no-invalid-regexp): Invalid regular expression: Duplicated flag ╭─[no_invalid_regexp.tsx:1:19] 1 │ new RegExp('.', 'aaz'); · ▲ + · ╰── flag 'a' already specified ╰──── + help: Remove the duplicated 'a' flag from the regular expression flags ⚠ eslint(no-invalid-regexp): Invalid regular expression: Duplicated flag ╭─[no_invalid_regexp.tsx:1:20] 1 │ new RegExp('.', 'azz'); · ▲ + · ╰── flag 'z' already specified ╰──── + help: Remove the duplicated 'z' flag from the regular expression flags ⚠ eslint(no-invalid-regexp): Invalid regular expression: Duplicated flag ╭─[no_invalid_regexp.tsx:1:20] 1 │ new RegExp('.', 'aga'); · ▲ + · ╰── flag 'a' already specified ╰──── + help: Remove the duplicated 'a' flag from the regular expression flags ⚠ eslint(no-invalid-regexp): Invalid regular expression: Duplicated flag ╭─[no_invalid_regexp.tsx:1:19] 1 │ new RegExp('.', 'uu'); · ▲ + · ╰── flag 'u' already specified ╰──── + help: Remove the duplicated 'u' flag from the regular expression flags ⚠ eslint(no-invalid-regexp): Invalid regular expression: Unknown flag ╭─[no_invalid_regexp.tsx:1:18] 1 │ new RegExp('.', 'ouo'); · ▲ + · ╰── flag 'o' is not a valid regular expression flag ╰──── + note: Valid flags are: d (indices), g (global), i (ignore case), m (multiline), + s (dot all), u (unicode), v (unicode sets), y (sticky) ⚠ eslint(no-invalid-regexp): Invalid regular expression: Could not parse the entire pattern ╭─[no_invalid_regexp.tsx:1:13] @@ -165,19 +204,28 @@ source: crates/oxc_linter/src/tester.rs ╭─[no_invalid_regexp.tsx:1:19] 1 │ RegExp(')' + '', 'a'); · ▲ + · ╰── flag 'a' is not a valid regular expression flag ╰──── + note: Valid flags are: d (indices), g (global), i (ignore case), m (multiline), + s (dot all), u (unicode), v (unicode sets), y (sticky) ⚠ eslint(no-invalid-regexp): Invalid regular expression: Unknown flag ╭─[no_invalid_regexp.tsx:1:23] 1 │ new RegExp('.' + '', 'az'); · ▲ + · ╰── flag 'a' is not a valid regular expression flag ╰──── + note: Valid flags are: d (indices), g (global), i (ignore case), m (multiline), + s (dot all), u (unicode), v (unicode sets), y (sticky) ⚠ eslint(no-invalid-regexp): Invalid regular expression: Unknown flag ╭─[no_invalid_regexp.tsx:1:23] 1 │ new RegExp(pattern, 'az'); · ▲ + · ╰── flag 'z' is not a valid regular expression flag ╰──── + note: Valid flags are: d (indices), g (global), i (ignore case), m (multiline), + s (dot all), u (unicode), v (unicode sets), y (sticky) ⚠ eslint(no-invalid-regexp): Invalid regular expression: Unterminated character class ╭─[no_invalid_regexp.tsx:1:13] @@ -190,13 +238,17 @@ source: crates/oxc_linter/src/tester.rs ╭─[no_invalid_regexp.tsx:1:19] 1 │ new RegExp('.', 'uv'); · ▲ + · ╰── the 'v' flag cannot be used when the 'u' flag is specified ╰──── + help: Specify only one of 'u' or 'v' flags ⚠ eslint(no-invalid-regexp): Invalid regular expression: `u` and `v` flags should be used alone ╭─[no_invalid_regexp.tsx:1:23] 1 │ new RegExp(pattern, 'uv'); · ▲ + · ╰── the 'v' flag cannot be used when the 'u' flag is specified ╰──── + help: Specify only one of 'u' or 'v' flags ⚠ eslint(no-invalid-regexp): Invalid regular expression: Character class range out of order ╭─[no_invalid_regexp.tsx:1:15]