Skip to content

Commit

Permalink
refactor(noNonoctalDecimalEscape): check member name
Browse files Browse the repository at this point in the history
  • Loading branch information
Conaclos committed Mar 3, 2025
1 parent b9d438b commit 1976a6c
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ use biome_analyze::{
};
use biome_console::markup;
use biome_diagnostics::Severity;
use biome_js_factory::make;
use biome_js_syntax::JsStringLiteralExpression;
use biome_rowan::{AstNode, BatchMutationExt, TextRange};
use biome_js_syntax::{
JsLiteralMemberName, JsStringLiteralExpression, JsSyntaxKind, JsSyntaxToken,
};
use biome_rowan::{AstNode, BatchMutationExt, TextRange, declare_node_union};
use rustc_hash::FxHashSet;
use std::ops::Range;

Expand Down Expand Up @@ -78,15 +79,15 @@ pub struct RuleState {
}

impl Rule for NoNonoctalDecimalEscape {
type Query = Ast<JsStringLiteralExpression>;
type Query = Ast<AnyJsStringLiteral>;
type State = RuleState;
type Signals = Box<[Self::State]>;
type Options = ();

fn run(ctx: &RuleContext<Self>) -> Self::Signals {
let node = ctx.query();
let mut result = Vec::new();
let Some(token) = node.value_token().ok() else {
let Some(token) = node.string_literal_token() else {
return result.into_boxed_slice();
};
let text = token.text_trimmed();
Expand Down Expand Up @@ -205,14 +206,14 @@ impl Rule for NoNonoctalDecimalEscape {
) -> Option<JsRuleAction> {
let mut mutation = ctx.root().begin();
let node = ctx.query();
let prev_token = node.value_token().ok()?;
let prev_token = node.string_literal_token()?;
let replaced = safe_replace_by_range(
prev_token.text_trimmed().to_string(),
replace_string_range.clone(),
replace_to,
)?;

let next_token = make::ident(&replaced);
let next_token = JsSyntaxToken::new_detached(prev_token.kind(), &replaced, [], []);

mutation.replace_token(prev_token, next_token);

Expand All @@ -229,6 +230,22 @@ impl Rule for NoNonoctalDecimalEscape {
}
}

declare_node_union! {
/// Any string literal excluding JsxString.
pub AnyJsStringLiteral = JsStringLiteralExpression | JsLiteralMemberName
}
impl AnyJsStringLiteral {
pub fn string_literal_token(&self) -> Option<JsSyntaxToken> {
match self {
AnyJsStringLiteral::JsStringLiteralExpression(node) => node.value_token().ok(),
AnyJsStringLiteral::JsLiteralMemberName(node) => node
.value()
.ok()
.filter(|token| token.kind() == JsSyntaxKind::JS_STRING_LITERAL),
}
}
}

fn safe_replace_by_range(
mut target: String,
range: Range<usize>,
Expand Down
25 changes: 6 additions & 19 deletions crates/biome_js_analyze/src/lint/nursery/no_octal_escape.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ use biome_analyze::{
};
use biome_console::markup;
use biome_diagnostics::Severity;
use biome_js_syntax::{JsLiteralMemberName, JsStringLiteralExpression, JsSyntaxToken};
use biome_rowan::{BatchMutationExt, SyntaxResult, TextRange, declare_node_union};
use biome_js_syntax::JsSyntaxToken;
use biome_rowan::{BatchMutationExt, TextRange};

use crate::JsRuleAction;
use crate::{JsRuleAction, lint::correctness::no_nonoctal_decimal_escape::AnyJsStringLiteral};

declare_lint_rule! {
/// Disallow octal escape sequences in string literals
Expand Down Expand Up @@ -47,7 +47,7 @@ impl Rule for NoOctalEscape {
type Options = ();

fn run(ctx: &RuleContext<Self>) -> Self::Signals {
let token = ctx.query().value_token().ok()?;
let token = ctx.query().string_literal_token()?;
let mut it = token.text_trimmed().bytes().enumerate();
while let Some((index, byte)) = it.next() {
if byte == b'\\' {
Expand All @@ -73,7 +73,7 @@ impl Rule for NoOctalEscape {
ctx: &RuleContext<Self>,
RuleState { index, len }: &Self::State,
) -> Option<RuleDiagnostic> {
let token = ctx.query().value_token().ok()?;
let token = ctx.query().string_literal_token()?;
let escape_start = token
.text_trimmed_range()
.start()
Expand All @@ -91,7 +91,7 @@ impl Rule for NoOctalEscape {
ctx: &RuleContext<Self>,
RuleState { index, len }: &Self::State,
) -> Option<JsRuleAction> {
let token = ctx.query().value_token().ok()?;
let token = ctx.query().string_literal_token()?;
let text = token.text_trimmed();
let octal = &text[(index + 1)..(index + len)];
let codepoint = u32::from_str_radix(octal, 8).ok()?;
Expand Down Expand Up @@ -120,19 +120,6 @@ impl Rule for NoOctalEscape {
}
}

declare_node_union! {
/// Any string literal excluding JsxString.
pub AnyJsStringLiteral = JsStringLiteralExpression | JsLiteralMemberName
}
impl AnyJsStringLiteral {
pub fn value_token(&self) -> SyntaxResult<JsSyntaxToken> {
match self {
AnyJsStringLiteral::JsStringLiteralExpression(node) => node.value_token(),
AnyJsStringLiteral::JsLiteralMemberName(node) => node.value(),
}
}
}

pub struct RuleState {
// Index of the escape sequence (starts with `\`)
index: usize,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,7 @@ let x = "\0 \8"
let x = "\01\8"
let x = "\0\1\8"
let x = "\0\\n\8"

let x = {
"\8": 0,
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
---
source: crates/biome_js_analyze/tests/spec_tests.rs
expression: invalid.js
snapshot_kind: text
---
# Input
```js
Expand Down Expand Up @@ -50,6 +49,9 @@ let x = "\01\8"
let x = "\0\1\8"
let x = "\0\\n\8"

let x = {
"\8": 0,
}
```

# Diagnostics
Expand Down Expand Up @@ -1370,6 +1372,7 @@ invalid.js:44:15 lint/correctness/noNonoctalDecimalEscape FIXABLE ━━━━
> 44 │ let x = "\0\\n\8"
│ ^^
45 │
46 │ let x = {
i The nonoctal decimal escape is a deprecated syntax that is left for compatibility and should not be used.
Expand All @@ -1380,6 +1383,26 @@ invalid.js:44:15 lint/correctness/noNonoctalDecimalEscape FIXABLE ━━━━
44 │ - let·x·=·"\0\\n\8"
44 │ + let·x·=·"\0\\n8"
45 45 │
46 46 │ let x = {
```

```
invalid.js:47:6 lint/correctness/noNonoctalDecimalEscape FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
× Don't use `\8` and `\9` escape sequences in string literals.
46 │ let x = {
> 47 │ "\8": 0,
│ ^^
48 │ }
i The nonoctal decimal escape is a deprecated syntax that is left for compatibility and should not be used.
i Unsafe fix: Replace \8 with 8. This maintains the current functionality.
47 │ ····"\8":·0,
│ -
```

0 comments on commit 1976a6c

Please sign in to comment.