Skip to content

Commit aa45604

Browse files
jellymysteryven
andauthored
feat(linter/eslint): Implement no-multi-str (#4038)
Rule Detail: [link](https://eslint.org/docs/latest/rules/no-multi-str) --------- Co-authored-by: wenzhe <mysteryven@gmail.com>
1 parent 7fe2a2f commit aa45604

File tree

3 files changed

+120
-0
lines changed

3 files changed

+120
-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;
@@ -449,6 +450,7 @@ oxc_macros::declare_all_lint_rules! {
449450
eslint::no_caller,
450451
eslint::no_case_declarations,
451452
eslint::no_class_assign,
453+
eslint::no_multi_str,
452454
eslint::require_await,
453455
eslint::no_compare_neg_zero,
454456
eslint::no_cond_assign,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
use oxc_ast::AstKind;
2+
use oxc_diagnostics::OxcDiagnostic;
3+
use oxc_macros::declare_oxc_lint;
4+
use oxc_span::Span;
5+
6+
use crate::{context::LintContext, rule::Rule, AstNode};
7+
8+
fn no_multi_str_diagnostic(span0: Span) -> OxcDiagnostic {
9+
OxcDiagnostic::warn("eslint(no-multi-str): Unexpected multi string.").with_label(span0)
10+
}
11+
12+
#[derive(Debug, Default, Clone)]
13+
pub struct NoMultiStr;
14+
15+
declare_oxc_lint!(
16+
/// ### What it does
17+
///
18+
/// Disallow multiline strings.
19+
///
20+
/// ### Why is this bad?
21+
///
22+
/// Some consider this to be a bad practice as it was an undocumented feature of JavaScript
23+
/// that was only formalized later.
24+
///
25+
/// ### Example
26+
/// ```javascript
27+
/// var x = "Line 1 \
28+
/// Line 2";
29+
/// ```
30+
NoMultiStr,
31+
style,
32+
);
33+
34+
impl Rule for NoMultiStr {
35+
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
36+
if let AstKind::StringLiteral(literal) = node.kind() {
37+
let source = literal.span.source_text(ctx.source_text());
38+
// https://github.com/eslint/eslint/blob/9e6d6405c3ee774c2e716a3453ede9696ced1be7/lib/shared/ast-utils.js#L12
39+
let position =
40+
source.find(|ch| matches!(ch, '\r' | '\n' | '\u{2028}' | '\u{2029}')).unwrap_or(0);
41+
if position != 0 {
42+
// We found the "newline" character but want to highlight the '\', so go back one
43+
// character.
44+
let multi_span_start =
45+
literal.span.start + u32::try_from(position).unwrap_or_default() - 1;
46+
ctx.diagnostic(no_multi_str_diagnostic(Span::new(
47+
multi_span_start,
48+
multi_span_start + 1,
49+
)));
50+
}
51+
}
52+
}
53+
}
54+
55+
#[test]
56+
fn test() {
57+
use crate::tester::Tester;
58+
59+
let pass = vec![
60+
"var a = 'Line 1 Line 2';",
61+
"var a = <div>
62+
<h1>Wat</h1>
63+
</div>;", // { "ecmaVersion": 6, "parserOptions": { "ecmaFeatures": { "jsx": true } } }
64+
];
65+
66+
let fail = vec![
67+
"var x = 'Line 1 \\
68+
Line 2'",
69+
"test('Line 1 \\
70+
Line 2');",
71+
"'foo\\\rbar';",
72+
"'foo\\
bar';",
73+
"'foo\\
ar';",
74+
"'\\
still fails';",
75+
];
76+
77+
Tester::new(NoMultiStr::NAME, pass, fail).test_and_snapshot();
78+
}

crates/oxc_linter/src/snapshots/no_multi_str.snap

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

0 commit comments

Comments
 (0)