From f7e15769dadb18ad8aaf1cf45c7cc378192bd4d5 Mon Sep 17 00:00:00 2001 From: tudorbarbu Date: Wed, 21 Feb 2024 09:02:20 +0200 Subject: [PATCH] feat(linter): eslint no-nonoctal-decimal-escape (#2428) Rule [source](https://github.com/eslint/eslint/blob/main/lib/rules/no-nonoctal-decimal-escape.js) Rule [tests](https://github.com/eslint/eslint/blob/main/tests/lib/rules/no-nonoctal-decimal-escape.js) I created a basic sticky regex implementation based on what I could find about it, since rust does not have support for that. There might be a better place to keep it instead of this rule file --------- Co-authored-by: Boshen --- crates/oxc_linter/src/rules.rs | 2 + .../eslint/no_nonoctal_decimal_escape.rs | 254 +++++++ .../snapshots/no_nonoctal_decimal_escape.snap | 648 ++++++++++++++++++ 3 files changed, 904 insertions(+) create mode 100644 crates/oxc_linter/src/rules/eslint/no_nonoctal_decimal_escape.rs create mode 100644 crates/oxc_linter/src/snapshots/no_nonoctal_decimal_escape.snap diff --git a/crates/oxc_linter/src/rules.rs b/crates/oxc_linter/src/rules.rs index 5a70a5e16..7a4de5ea2 100644 --- a/crates/oxc_linter/src/rules.rs +++ b/crates/oxc_linter/src/rules.rs @@ -73,6 +73,7 @@ mod eslint { pub mod no_mixed_operators; pub mod no_new_symbol; pub mod no_new_wrappers; + pub mod no_nonoctal_decimal_escape; pub mod no_obj_calls; pub mod no_prototype_builtins; pub mod no_redeclare; @@ -372,6 +373,7 @@ oxc_macros::declare_all_lint_rules! { eslint::no_mixed_operators, eslint::no_new_symbol, eslint::no_new_wrappers, + eslint::no_nonoctal_decimal_escape, eslint::no_obj_calls, eslint::no_prototype_builtins, eslint::no_redeclare, diff --git a/crates/oxc_linter/src/rules/eslint/no_nonoctal_decimal_escape.rs b/crates/oxc_linter/src/rules/eslint/no_nonoctal_decimal_escape.rs new file mode 100644 index 000000000..b71563ae6 --- /dev/null +++ b/crates/oxc_linter/src/rules/eslint/no_nonoctal_decimal_escape.rs @@ -0,0 +1,254 @@ +use lazy_static::lazy_static; +use oxc_ast::AstKind; +use oxc_diagnostics::{ + miette::{self, Diagnostic}, + thiserror::{self, Error}, +}; +use oxc_macros::declare_oxc_lint; +use oxc_span::Span; +use regex::{Captures, Match, Regex}; + +use crate::{context::LintContext, rule::Rule, AstNode}; + +#[derive(Debug, Error, Diagnostic)] +enum NoNonoctalDecimalEscapeDiagnostic { + #[error("eslint(no-nonoctal-decimal-escape): Don't use '{0}' escape sequence.")] + #[diagnostic( + severity(warning), + help("Replace '{0}' with '{1}'. This maintains the current functionality.") + )] + Replacement(String, String, #[label] Span), + + #[error("eslint(no-nonoctal-decimal-escape): Don't use '{0}' escape sequence.")] + #[diagnostic( + severity(warning), + help("Replace '{0}' with '{1}' to include the actual backslash character.") + )] + EscapeBackslash(String, String, #[label] Span), +} + +#[derive(Debug, Default, Clone)] +pub struct NoNonoctalDecimalEscape; + +declare_oxc_lint!( + /// ### What it does + /// This rule disallows \8 and \9 escape sequences in string literals + /// + /// ### Why is this bad? + /// ECMAScript specification treats \8 and \9 in string literals as a legacy feature + /// + /// ### Example + /// ```javascript + /// incorrect: + /// "\8" + /// "\9" + /// correct: + /// "8" + /// "\\9" + /// ``` + NoNonoctalDecimalEscape, + correctness +); + +impl Rule for NoNonoctalDecimalEscape { + fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { + if let AstKind::StringLiteral(literal) = node.kind() { + check_string(ctx, literal.span.source_text(ctx.source_text())); + } + } +} +trait StickyRegex { + // takes the start position and returns the match and the nextPosition + fn sticky_find<'h>(&self, haystack: &'h str, start: usize) -> (Option>, usize); + fn sticky_captures<'h>(&self, haystack: &'h str, start: usize) + -> (Option>, usize); +} + +impl StickyRegex for Regex { + fn sticky_find<'h>(&self, haystack: &'h str, start: usize) -> (Option>, usize) { + let m_opt = self.find_at(haystack, start); + if let Some(m) = m_opt { + if m.start() == start { + return (m_opt, m.end()); + } + } + (None, 0) + } + + fn sticky_captures<'h>( + &self, + haystack: &'h str, + start: usize, + ) -> (Option>, usize) { + let c_opt = self.captures_at(haystack, start); + if let Some(captures) = c_opt { + let capture = captures.get(0).unwrap(); + if capture.start() == start { + return (Some(captures), capture.end()); + } + } + (None, 0) + } +} + +fn quick_test(s: &str) -> bool { + let mut chars = s.chars().peekable(); + while let Some(c) = chars.next() { + if c == '\\' && chars.peek().is_some_and(|c| *c == '8' || *c == '9') { + return true; + } + } + false +} + +#[allow(clippy::cast_possible_truncation)] +fn check_string(ctx: &LintContext<'_>, string: &str) { + lazy_static! { + static ref NONOCTAL_REGEX: Regex = + Regex::new(r"(?:[^\\]|(?P\\.))*?(?P\\[89])").unwrap(); + } + + // Need at least 2 characters + if string.len() <= 1 { + return; + } + + if !quick_test(string) { + return; + } + + let mut start: usize = 0; + while let (Some(captures), new_start) = NONOCTAL_REGEX.sticky_captures(string, start) { + let previous_escape = captures.name("previousEscape"); + let decimal_escape = captures.name("decimalEscape").unwrap(); + let decimal_escape_span = + Span::new(decimal_escape.start() as u32, decimal_escape.end() as u32); + let decimal_escape_str = decimal_escape.as_str(); + + if let Some(prev_match) = previous_escape { + if prev_match.as_str().eq("\\0") { + ctx.diagnostic(NoNonoctalDecimalEscapeDiagnostic::Replacement( + prev_match.as_str().to_string() + decimal_escape_str, + "\\u00008".to_string(), + Span::new(prev_match.start() as u32, decimal_escape_span.end), + )); + ctx.diagnostic(NoNonoctalDecimalEscapeDiagnostic::Replacement( + decimal_escape_str.to_string(), + "\\u0038".to_string(), + decimal_escape_span, + )); + } + } else { + ctx.diagnostic(NoNonoctalDecimalEscapeDiagnostic::Replacement( + decimal_escape_str.to_string(), + decimal_escape_str[1..].to_string(), + decimal_escape_span, + )); + } + + ctx.diagnostic(NoNonoctalDecimalEscapeDiagnostic::EscapeBackslash( + decimal_escape_str.to_string(), + format!("\\{decimal_escape_str}"), + decimal_escape_span, + )); + + start = new_start; + } +} + +#[test] +fn test() { + use crate::tester::Tester; + + let pass = vec![ + r"8", + r"var \u8888", + r"/\8/", + r"''", + r"'foo'", + r"'8'", + r"'9'", + r"'foo8'", + r"'foo9bar'", + r"'\ '", + r"'\\'", + r"'\a'", + r"'\n'", + r"'\0'", + r"'\1'", + r"'\7'", + r"'\01'", + r"'\08'", + r"'\19'", + r"'\t9'", + r"'\๐Ÿ‘8'", + r"'\\8'", + r"'\\9'", + r"'\\8\\9'", + r"'\\ \\8'", + r"'\\\\9'", + r"'\\9bar'", + r"'a\\8'", + r"'foo\\8'", + r"'foo\\8bar'", + r"'9\\9'", + r"'n\n8'", + r"'n\nn\n8'", + r"'\1.8'", + r"'\1\28'", + r"'\x99'", + r"'\\\x38'", + r"\u99999", + r"'\\\n8'", + r"'\\\n\\\\9'", + ]; + + let fail = vec![ + r"'\8'", + r"'\9'", + r#""\8""#, + r"'f\9'", + r"'xo\9'", + r"'foo\9'", + r"'foo\8bar'", + r"'๐Ÿ‘\8'", + r"'\\\8'", + r"'\\\\\9'", + r"'foo\\\8'", + r"'\ \8'", + r"'\1\9'", + r"'foo\1\9'", + r"'\n\n\8\n'", + r"'\n.\n\8\n'", + r"'\n.\nn\8\n'", + r"'\๐Ÿ‘\8'", + r"'\\8\9'", + r"'\8\\9'", + r"'\8 \\9'", + r"'\8\8'", + r"'\9\8'", + r"'foo\8bar\9baz'", + r"'\8\1\9'", + r"'\9\n9\\9\9'", + r"'\8\\\9'", + r"var foo = '\8'; bar('\9')", + r"var foo = '8'\n bar = '\\9'", + r"'\\n\8'", + r"'\\n\9'", + r"'\\\\n\8'", + r"'foo\\nbar\9baz'", + r"'\0\8'", + r"'foo\0\9bar'", + r"'\1\0\8'", + r"'\0\8\9'", + r"'\8\0\9'", + r"'0\8'", + r"'\\0\8'", + r"'\0 \8'", + r"'\01\8'", + r"'\0\1\8'", + r"'\0\\n\8'", + ]; + + Tester::new(NoNonoctalDecimalEscape::NAME, pass, fail).test_and_snapshot(); +} diff --git a/crates/oxc_linter/src/snapshots/no_nonoctal_decimal_escape.snap b/crates/oxc_linter/src/snapshots/no_nonoctal_decimal_escape.snap new file mode 100644 index 000000000..27e46ff97 --- /dev/null +++ b/crates/oxc_linter/src/snapshots/no_nonoctal_decimal_escape.snap @@ -0,0 +1,648 @@ +--- +source: crates/oxc_linter/src/tester.rs +expression: no_nonoctal_decimal_escape +--- + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:2] + 1 โ”‚ '\8' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '8'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:2] + 1 โ”‚ '\8' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\\8' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\9' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:2] + 1 โ”‚ '\9' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\9' with '9'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\9' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:2] + 1 โ”‚ '\9' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\9' with '\\9' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:2] + 1 โ”‚ "\8" + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '8'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:2] + 1 โ”‚ "\8" + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\\8' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\9' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:3] + 1 โ”‚ 'f\9' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\9' with '9'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\9' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:3] + 1 โ”‚ 'f\9' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\9' with '\\9' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\9' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:4] + 1 โ”‚ 'xo\9' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\9' with '9'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\9' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:4] + 1 โ”‚ 'xo\9' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\9' with '\\9' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\9' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:5] + 1 โ”‚ 'foo\9' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\9' with '9'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\9' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:5] + 1 โ”‚ 'foo\9' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\9' with '\\9' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:5] + 1 โ”‚ 'foo\8bar' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '8'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:5] + 1 โ”‚ 'foo\8bar' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\\8' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:4] + 1 โ”‚ '๐Ÿ‘\8' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '8'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:4] + 1 โ”‚ '๐Ÿ‘\8' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\\8' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:4] + 1 โ”‚ '\\\8' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\\8' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\9' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:6] + 1 โ”‚ '\\\\\9' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\9' with '\\9' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:7] + 1 โ”‚ 'foo\\\8' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\\8' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:4] + 1 โ”‚ '\ \8' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\\8' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\9' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:4] + 1 โ”‚ '\1\9' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\9' with '\\9' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\9' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:7] + 1 โ”‚ 'foo\1\9' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\9' with '\\9' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:6] + 1 โ”‚ '\n\n\8\n' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\\8' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:7] + 1 โ”‚ '\n.\n\8\n' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\\8' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:8] + 1 โ”‚ '\n.\nn\8\n' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\\8' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:5] + 1 โ”‚ '\๐Ÿ‘\8' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\\8' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\9' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:5] + 1 โ”‚ '\\8\9' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\9' with '\\9' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:2] + 1 โ”‚ '\8\\9' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '8'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:2] + 1 โ”‚ '\8\\9' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\\8' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:2] + 1 โ”‚ '\8 \\9' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '8'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:2] + 1 โ”‚ '\8 \\9' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\\8' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:2] + 1 โ”‚ '\8\8' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '8'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:2] + 1 โ”‚ '\8\8' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\\8' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:4] + 1 โ”‚ '\8\8' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '8'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:4] + 1 โ”‚ '\8\8' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\\8' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\9' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:2] + 1 โ”‚ '\9\8' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\9' with '9'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\9' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:2] + 1 โ”‚ '\9\8' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\9' with '\\9' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:4] + 1 โ”‚ '\9\8' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '8'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:4] + 1 โ”‚ '\9\8' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\\8' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:5] + 1 โ”‚ 'foo\8bar\9baz' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '8'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:5] + 1 โ”‚ 'foo\8bar\9baz' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\\8' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\9' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:10] + 1 โ”‚ 'foo\8bar\9baz' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\9' with '9'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\9' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:10] + 1 โ”‚ 'foo\8bar\9baz' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\9' with '\\9' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:2] + 1 โ”‚ '\8\1\9' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '8'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:2] + 1 โ”‚ '\8\1\9' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\\8' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\9' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:6] + 1 โ”‚ '\8\1\9' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\9' with '\\9' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\9' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:2] + 1 โ”‚ '\9\n9\\9\9' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\9' with '9'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\9' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:2] + 1 โ”‚ '\9\n9\\9\9' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\9' with '\\9' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\9' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:10] + 1 โ”‚ '\9\n9\\9\9' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\9' with '\\9' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:2] + 1 โ”‚ '\8\\\9' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '8'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:2] + 1 โ”‚ '\8\\\9' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\\8' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\9' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:6] + 1 โ”‚ '\8\\\9' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\9' with '\\9' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:2] + 1 โ”‚ var foo = '\8'; bar('\9') + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '8'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:2] + 1 โ”‚ var foo = '\8'; bar('\9') + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\\8' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\9' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:2] + 1 โ”‚ var foo = '\8'; bar('\9') + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\9' with '9'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\9' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:2] + 1 โ”‚ var foo = '\8'; bar('\9') + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\9' with '\\9' to include the actual backslash character. + + ร— Invalid Unicode escape sequence + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:15] + 1 โ”‚ var foo = '8'\n bar = '\\9' + ยท โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + + ร— Expected a semicolon or an implicit semicolon after a statement, but found none + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:14] + 1 โ”‚ var foo = '8'\n bar = '\\9' + ยท โ–ฒ + โ•ฐโ”€โ”€โ”€โ”€ + help: Try insert a semicolon here + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:5] + 1 โ”‚ '\\n\8' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\\8' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\9' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:5] + 1 โ”‚ '\\n\9' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\9' with '\\9' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:7] + 1 โ”‚ '\\\\n\8' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\\8' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\9' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:11] + 1 โ”‚ 'foo\\nbar\9baz' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\9' with '\\9' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\0\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:2] + 1 โ”‚ '\0\8' + ยท โ”€โ”€โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\0\8' with '\u00008'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:4] + 1 โ”‚ '\0\8' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\u0038'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:4] + 1 โ”‚ '\0\8' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\\8' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\0\9' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:5] + 1 โ”‚ 'foo\0\9bar' + ยท โ”€โ”€โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\0\9' with '\u00008'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\9' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:7] + 1 โ”‚ 'foo\0\9bar' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\9' with '\u0038'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\9' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:7] + 1 โ”‚ 'foo\0\9bar' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\9' with '\\9' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\0\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:4] + 1 โ”‚ '\1\0\8' + ยท โ”€โ”€โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\0\8' with '\u00008'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:6] + 1 โ”‚ '\1\0\8' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\u0038'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:6] + 1 โ”‚ '\1\0\8' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\\8' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\0\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:2] + 1 โ”‚ '\0\8\9' + ยท โ”€โ”€โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\0\8' with '\u00008'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:4] + 1 โ”‚ '\0\8\9' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\u0038'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:4] + 1 โ”‚ '\0\8\9' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\\8' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\9' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:6] + 1 โ”‚ '\0\8\9' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\9' with '9'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\9' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:6] + 1 โ”‚ '\0\8\9' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\9' with '\\9' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:2] + 1 โ”‚ '\8\0\9' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '8'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:2] + 1 โ”‚ '\8\0\9' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\\8' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\0\9' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:4] + 1 โ”‚ '\8\0\9' + ยท โ”€โ”€โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\0\9' with '\u00008'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\9' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:6] + 1 โ”‚ '\8\0\9' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\9' with '\u0038'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\9' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:6] + 1 โ”‚ '\8\0\9' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\9' with '\\9' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:3] + 1 โ”‚ '0\8' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '8'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:3] + 1 โ”‚ '0\8' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\\8' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:5] + 1 โ”‚ '\\0\8' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\\8' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\0\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:2] + 1 โ”‚ '\0 \8' + ยท โ”€โ”€โ”€โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\0\8' with '\u00008'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:5] + 1 โ”‚ '\0 \8' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\u0038'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:5] + 1 โ”‚ '\0 \8' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\\8' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\0\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:2] + 1 โ”‚ '\01\8' + ยท โ”€โ”€โ”€โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\0\8' with '\u00008'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:5] + 1 โ”‚ '\01\8' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\u0038'. This maintains the current functionality. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:5] + 1 โ”‚ '\01\8' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\\8' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:6] + 1 โ”‚ '\0\1\8' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\\8' to include the actual backslash character. + + โš  eslint(no-nonoctal-decimal-escape): Don't use '\8' escape sequence. + โ•ญโ”€[no_nonoctal_decimal_escape.tsx:1:7] + 1 โ”‚ '\0\\n\8' + ยท โ”€โ”€ + โ•ฐโ”€โ”€โ”€โ”€ + help: Replace '\8' with '\\8' to include the actual backslash character. +