diff --git a/crates/oxc_linter/src/rules/eslint/no_octal_escape.rs b/crates/oxc_linter/src/rules/eslint/no_octal_escape.rs index 80759fbf313d6..634ef82b88045 100644 --- a/crates/oxc_linter/src/rules/eslint/no_octal_escape.rs +++ b/crates/oxc_linter/src/rules/eslint/no_octal_escape.rs @@ -7,7 +7,7 @@ use regex::Regex; use crate::{context::LintContext, rule::Rule, AstNode}; fn no_octal_escape_diagnostic(span: Span, sequence: &str) -> OxcDiagnostic { - OxcDiagnostic::warn(format!("Don't use octal: '{}'. Use '\\u....' instead.", sequence)) + OxcDiagnostic::warn(format!("Don't use octal: '\\{}'. Use '\\u....' instead.", sequence)) .with_label(span) } @@ -44,17 +44,12 @@ impl Rule for NoOctalEscape { fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { if let AstKind::StringLiteral(literal) = node.kind() { let octal_escape_pattern = - // /^(?:[^\\]|\\.)*?\\([0-3][0-7]{1,2}|[4-7][0-7]|0(?=[89])|[1-7])/su - Regex::new(r"^(?:[^\\]|\\.)*?\\([0-3][0-7]{1,2}|[4-7][0-7]|0[0-7]|[1-7])") + Regex::new(r"^(?:[^\\]|\\.)*?\\([0-3][0-7]{1,2}|[4-7][0-7]|(08|09)|[1-7])") .unwrap(); - if let Some(captures) = octal_escape_pattern.captures(&literal.value) { - if let Some(sequence) = captures.get(1) { - let escape_seq = sequence.as_str(); - if escape_seq.starts_with('0') - && escape_seq.len() == 2 - && &escape_seq[1..] >= "8" - { + if let Some(raw) = &literal.raw { + if let Some(captures) = octal_escape_pattern.captures(raw) { + if let Some(sequence) = captures.get(1) { ctx.diagnostic(no_octal_escape_diagnostic(literal.span, sequence.as_str())); } } @@ -68,31 +63,31 @@ fn test() { use crate::tester::Tester; let pass = vec![ - "var foo = \"\x51\";", - "let foo = \"foo \\251 bar\"", - "var foo = /([abc]) \\1/g;", - "var foo = '\0';", - "'\\0'", - "'\\8'", - "'\\9'", - "'\\0 '", - "' \\0'", - "'a\\0'", - "'\\0a'", - "'a\\8a'", - "'\\0\\8'", - "'\\8\\0'", - "'\\80'", - "'\\81'", - "'\\\\'", - "'\\\\0'", - "'\\\\08'", - "'\\\\1'", - "'\\\\01'", - "'\\\\12'", - "'\\\\\\0'", - "'\\\\\\8'", - "'\\0\\\\'", + r#"var foo = "\x51";"#, + r#"var foo = "foo \\251 bar";"#, + r#"var foo = /([abc]) \1/g;"#, + r#"var foo = '\0';"#, + r#"'\0'"#, + r#"'\8'"#, + r#"'\9'"#, + r#"'\0 '"#, + r#"' \0'"#, + r#"'a\0'"#, + r#"'\0a'"#, + r#"'a\8a'"#, + r#"'\0\8'"#, + r#"'\8\0'"#, + r#"'\80'"#, + r#"'\81'"#, + r#"'\\'"#, + r#"'\\0'"#, + r#"'\\08'"#, + r#"'\\1'"#, + r#"'\\01'"#, + r#"'\\12'"#, + r#"'\\\0'"#, + r#"'\\\8'"#, + r#"'\0\\'"#, "'0'", "'1'", "'8'", @@ -100,12 +95,12 @@ fn test() { "'08'", "'80'", "'12'", - "'\\a'", - "'\\n'", + r#"'\a'"#, + r#"'\n'"#, ]; let fail = vec![ - "var foo = \"foo \\01 bar\";", + r#"var foo = "foo \01 bar";"#, r#"var foo = "foo \000 bar";"#, r#"var foo = "foo \377 bar";"#, r#"var foo = "foo \378 bar";"#, @@ -123,49 +118,49 @@ fn test() { r#"var foo = "foo \400 bar";"#, r#"var foo = "\t\1";"#, r#"var foo = "\\\751";"#, - "'\0\\1'", - "'\0 \\1'", - "'\0\01'", - "'\0 \01'", - "'\0a\\1'", - "'\0a\01'", - "'\0\08'", - "'\\1'", - "'\\2'", - "'\\7'", - "'\00'", - "'\01'", - "'\02'", - "'\07'", - "'\08'", - "'\09'", - "'\\10'", - "'\\12'", - "' \\1'", - "'\\1 '", - "'a\\1'", - "'\\1a'", - "'a\\1a'", - "' \01'", - "'\01 '", - "'a\01'", - "'\01a'", - "'a\01a'", - "'a\08a'", - "'\n\\1'", - "'\n\01'", - "'\n\08'", - "'\\\\1'", - "'\\\01'", - "'\\\08'", - "'\\ - \\1'", - "'\01\02'", - "'\02\01'", - "'\01\\2'", - "'\\2\01'", - "'\08\\1'", - "'foo \\1 bar \\2'", + r#"'\0\1'"#, + r#"'\0 \1'"#, + r#"#\0\01'"#, + r#"'\0 \01'"#, + r#"'\0a\1'"#, + r#"'\0a\01'"#, + r#"'\0\08'"#, + r#"'\1'"#, + r#"'\2'"#, + r#"'\7'"#, + r#"'\00'"#, + r#"'\01'"#, + r#"'\02'"#, + r#"'\07'"#, + r#"'\08'"#, + r#"'\09'"#, + r#"'\10'"#, + r#"'\12'"#, + r#"' \1'"#, + r#"'\1 '"#, + r#"'a\1'"#, + r#"'\1a'"#, + r#"'a\1a'"#, + r#"' \01'"#, + r#"'\01 '"#, + r#"'a\01'"#, + r#"'\01a'"#, + r#"'a\01a'"#, + r#"'a\08a'"#, + r#"'\n\1'"#, + r#"'\n\01'"#, + r#"'\n\08'"#, + r#"'\\\1'"#, + r#"'\\\01'"#, + r#"'\\\08'"#, + r#"'\\ + \\1'"#, + r#"'\01\02'"#, + r#"'\02\01'"#, + r#"'\01\2'"#, + r#"'\2\01'"#, + r#"'\08\1'"#, + r#"'foo \1 bar \2'"#, ]; Tester::new(NoOctalEscape::NAME, NoOctalEscape::CATEGORY, pass, fail).test_and_snapshot(); diff --git a/crates/oxc_linter/src/snapshots/eslint_no_octal_escape.snap b/crates/oxc_linter/src/snapshots/eslint_no_octal_escape.snap new file mode 100644 index 0000000000000..43b2a83fa5328 --- /dev/null +++ b/crates/oxc_linter/src/snapshots/eslint_no_octal_escape.snap @@ -0,0 +1,383 @@ +--- +source: crates/oxc_linter/src/tester.rs +snapshot_kind: text +--- + ⚠ eslint(no-octal-escape): Don't use octal: '\01'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:11] + 1 │ var foo = "foo \01 bar"; + · ───────────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\000'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:11] + 1 │ var foo = "foo \000 bar"; + · ────────────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\377'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:11] + 1 │ var foo = "foo \377 bar"; + · ────────────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\37'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:11] + 1 │ var foo = "foo \378 bar"; + · ────────────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\37'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:11] + 1 │ var foo = "foo \37a bar"; + · ────────────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\3'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:11] + 1 │ var foo = "foo \381 bar"; + · ────────────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\3'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:11] + 1 │ var foo = "foo \3a1 bar"; + · ────────────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\251'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:11] + 1 │ var foo = "foo \251 bar"; + · ────────────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\25'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:11] + 1 │ var foo = "foo \258 bar"; + · ────────────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\25'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:11] + 1 │ var foo = "foo \25a bar"; + · ────────────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\3'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:11] + 1 │ var foo = "\3s51"; + · ─────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\77'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:11] + 1 │ var foo = "\77"; + · ───── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\7'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:11] + 1 │ var foo = "\78"; + · ───── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\5'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:11] + 1 │ var foo = "\5a"; + · ───── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\75'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:11] + 1 │ var foo = "\751"; + · ────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\40'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:11] + 1 │ var foo = "foo \400 bar"; + · ────────────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\1'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:11] + 1 │ var foo = "\t\1"; + · ────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\75'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:11] + 1 │ var foo = "\\\751"; + · ──────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\1'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ '\0\1' + · ────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\1'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ '\0 \1' + · ─────── + ╰──── + + × Invalid Unicode escape sequence + ╭─[no_octal_escape.tsx:1:3] + 1 │ #\0\01' + · ─ + ╰──── + + × Invalid Unicode escape sequence + ╭─[no_octal_escape.tsx:1:5] + 1 │ #\0\01' + · ─ + ╰──── + + × Unterminated string + ╭─[no_octal_escape.tsx:1:7] + 1 │ #\0\01' + · ─ + ╰──── + + × Expected `in` but found `Unknown` + ╭─[no_octal_escape.tsx:1:7] + 1 │ #\0\01' + · ┬ + · ╰── `in` expected + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\01'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ '\0 \01' + · ──────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\1'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ '\0a\1' + · ─────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\01'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ '\0a\01' + · ──────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\08'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ '\0\08' + · ─────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\1'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ '\1' + · ──── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\2'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ '\2' + · ──── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\7'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ '\7' + · ──── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\00'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ '\00' + · ───── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\01'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ '\01' + · ───── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\02'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ '\02' + · ───── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\07'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ '\07' + · ───── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\08'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ '\08' + · ───── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\09'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ '\09' + · ───── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\10'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ '\10' + · ───── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\12'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ '\12' + · ───── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\1'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ ' \1' + · ───── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\1'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ '\1 ' + · ───── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\1'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ 'a\1' + · ───── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\1'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ '\1a' + · ───── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\1'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ 'a\1a' + · ────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\01'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ ' \01' + · ────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\01'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ '\01 ' + · ────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\01'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ 'a\01' + · ────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\01'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ '\01a' + · ────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\01'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ 'a\01a' + · ─────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\08'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ 'a\08a' + · ─────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\1'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ '\n\1' + · ────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\01'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ '\n\01' + · ─────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\08'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ '\n\08' + · ─────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\1'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ '\\\1' + · ────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\01'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ '\\\01' + · ─────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\08'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ '\\\08' + · ─────── + ╰──── + + × Unterminated string + ╭─[no_octal_escape.tsx:1:1] + 1 │ '\\ + · ──── + 2 │ \\1' + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\01'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ '\01\02' + · ──────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\02'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ '\02\01' + · ──────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\01'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ '\01\2' + · ─────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\2'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ '\2\01' + · ─────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\08'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ '\08\1' + · ─────── + ╰──── + + ⚠ eslint(no-octal-escape): Don't use octal: '\1'. Use '\u....' instead. + ╭─[no_octal_escape.tsx:1:1] + 1 │ 'foo \1 bar \2' + · ─────────────── + ╰────