Skip to content

Commit 68db5e4

Browse files
committed
feat(linter/eslint): Implement no-multi-str
Rule Detail: [link](https://eslint.org/docs/latest/rules/no-multi-str)
1 parent b007553 commit 68db5e4

File tree

3 files changed

+110
-0
lines changed

3 files changed

+110
-0
lines changed

crates/oxc_linter/src/rules.rs

+2
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ mod eslint {
7676
pub mod no_irregular_whitespace;
7777
pub mod no_iterator;
7878
pub mod no_loss_of_precision;
79+
pub mod no_multi_str;
7980
pub mod no_new;
8081
pub mod no_new_native_nonconstructor;
8182
pub mod no_new_wrappers;
@@ -446,6 +447,7 @@ oxc_macros::declare_all_lint_rules! {
446447
eslint::no_caller,
447448
eslint::no_case_declarations,
448449
eslint::no_class_assign,
450+
eslint::no_multi_str,
449451
eslint::require_await,
450452
eslint::no_compare_neg_zero,
451453
eslint::no_cond_assign,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
use lazy_static::lazy_static;
2+
use oxc_ast::AstKind;
3+
use oxc_diagnostics::OxcDiagnostic;
4+
use oxc_macros::declare_oxc_lint;
5+
use oxc_span::Span;
6+
use regex::Regex;
7+
8+
use crate::{context::LintContext, rule::Rule, AstNode};
9+
10+
fn no_multi_str_diagnostic(span0: Span) -> OxcDiagnostic {
11+
OxcDiagnostic::warn("eslint(no-multi-str): .").with_label(span0)
12+
}
13+
14+
#[derive(Debug, Default, Clone)]
15+
pub struct NoMultiStr;
16+
17+
declare_oxc_lint!(
18+
/// ### What it does
19+
///
20+
/// Disallow multiline strings.
21+
///
22+
/// ### Why is this bad?
23+
///
24+
/// Some consider this to be a bad practice as it was an undocumented feature of JavaScript
25+
/// that was only formalized later.
26+
///
27+
/// ### Example
28+
/// ```javascript
29+
/// var x = "Line 1 \
30+
/// Line 2";
31+
/// ```
32+
NoMultiStr,
33+
style,
34+
);
35+
36+
impl Rule for NoMultiStr {
37+
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
38+
// https://github.com/eslint/eslint/blob/9e6d6405c3ee774c2e716a3453ede9696ced1be7/lib/shared/ast-utils.js#L12
39+
lazy_static! {
40+
static ref MULTILINE_REGEX: Regex = Regex::new(r"\r\n|[\r\n\u2028\u2029]").unwrap();
41+
}
42+
43+
if let AstKind::StringLiteral(literal) = node.kind() {
44+
let source = literal.span.source_text(ctx.source_text());
45+
if MULTILINE_REGEX.is_match(source) {
46+
ctx.diagnostic(no_multi_str_diagnostic(literal.span));
47+
}
48+
} else {
49+
return;
50+
}
51+
}
52+
}
53+
54+
#[test]
55+
fn test() {
56+
use crate::tester::Tester;
57+
58+
let pass = vec![
59+
"var a = 'Line 1 Line 2';",
60+
"var a = <div>
61+
<h1>Wat</h1>
62+
</div>;", // { "ecmaVersion": 6, "parserOptions": { "ecmaFeatures": { "jsx": true } } }
63+
];
64+
65+
let fail = vec![
66+
"var x = 'Line 1 \\
67+
Line 2'",
68+
"test('Line 1 \\
69+
Line 2');",
70+
"'foo\\\rbar';",
71+
"'foo\\
bar';",
72+
"'foo\\
ar';",
73+
];
74+
75+
Tester::new(NoMultiStr::NAME, pass, fail).test_and_snapshot();
76+
}

crates/oxc_linter/src/snapshots/no_multi_str.snap

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
---
2+
source: crates/oxc_linter/src/tester.rs
3+
---
4+
eslint(no-multi-str): .
5+
╭─[no_multi_str.tsx:1:9]
6+
1 │ ╭─▶ var x = 'Line 1 \
7+
2 │ ╰─▶ Line 2'
8+
╰────
9+
10+
eslint(no-multi-str): .
11+
╭─[no_multi_str.tsx:1:6]
12+
1 │ ╭─▶ test('Line 1 \
13+
2 │ ╰─▶ Line 2');
14+
╰────
15+
16+
eslint(no-multi-str): .
17+
╭─[no_multi_str.tsx:1:1]
18+
1'foo\bar';
19+
· ─────────
20+
╰────
21+
22+
eslint(no-multi-str): .
23+
╭─[no_multi_str.tsx:1:1]
24+
1'foo\
bar';
25+
· ──────────
26+
╰────
27+
28+
eslint(no-multi-str): .
29+
╭─[no_multi_str.tsx:1:1]
30+
1'foo\
ar';
31+
· ─────────
32+
╰────

0 commit comments

Comments
 (0)