From 3a689faa6ebd4c348c896cfc410354f3e81394de Mon Sep 17 00:00:00 2001 From: Victorien Elvinger Date: Mon, 10 Jun 2024 13:16:33 +0200 Subject: [PATCH] fix(noStringCaseMismatch): ignore escape sequences (#3156) --- CHANGELOG.md | 10 + .../correctness/no_string_case_mismatch.rs | 98 ++- .../noStringCaseMismatch/invalid.js | 21 + .../noStringCaseMismatch/invalid.js.snap | 756 ++++++++++++++++++ .../noStringCaseMismatch/invalid.jsonc | 18 - .../noStringCaseMismatch/invalid.jsonc.snap | 499 ------------ .../correctness/noStringCaseMismatch/valid.js | 16 + .../noStringCaseMismatch/valid.js.snap | 23 + .../noStringCaseMismatch/valid.jsonc | 8 - .../noStringCaseMismatch/valid.jsonc.snap | 35 - 10 files changed, 900 insertions(+), 584 deletions(-) create mode 100644 crates/biome_js_analyze/tests/specs/correctness/noStringCaseMismatch/invalid.js create mode 100644 crates/biome_js_analyze/tests/specs/correctness/noStringCaseMismatch/invalid.js.snap delete mode 100644 crates/biome_js_analyze/tests/specs/correctness/noStringCaseMismatch/invalid.jsonc delete mode 100644 crates/biome_js_analyze/tests/specs/correctness/noStringCaseMismatch/invalid.jsonc.snap create mode 100644 crates/biome_js_analyze/tests/specs/correctness/noStringCaseMismatch/valid.js create mode 100644 crates/biome_js_analyze/tests/specs/correctness/noStringCaseMismatch/valid.js.snap delete mode 100644 crates/biome_js_analyze/tests/specs/correctness/noStringCaseMismatch/valid.jsonc delete mode 100644 crates/biome_js_analyze/tests/specs/correctness/noStringCaseMismatch/valid.jsonc.snap diff --git a/CHANGELOG.md b/CHANGELOG.md index f67485e945c0..e76b8ea6a47f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -71,6 +71,16 @@ our [guidelines for writing a good changelog entry](https://github.com/biomejs/b Contributed by @Conaclos +- [noStringCaseMismatch](https://biomejs.dev/linter/rules/no-string-case-mismatch/) now ignores escape sequences ([#3134](https://github.com/biomejs/biome/issues/3134)). + + The following code is no longer reported by the rule: + + ```js + s.toUpperCase() === "\u001b"; + ``` + + Contributed by @Conaclos + ### Parser #### New features diff --git a/crates/biome_js_analyze/src/lint/correctness/no_string_case_mismatch.rs b/crates/biome_js_analyze/src/lint/correctness/no_string_case_mismatch.rs index 381423191e61..b697b65d339e 100644 --- a/crates/biome_js_analyze/src/lint/correctness/no_string_case_mismatch.rs +++ b/crates/biome_js_analyze/src/lint/correctness/no_string_case_mismatch.rs @@ -89,14 +89,17 @@ impl Rule for NoStringCaseMismatch { fn action(ctx: &RuleContext, state: &Self::State) -> Option { let mut mutation = ctx.root().begin(); + let expected_value = state + .expected_case + .convert(state.literal.as_static_value()?.text()); mutation.replace_node( state.literal.clone(), AnyJsExpression::AnyJsLiteralExpression( AnyJsLiteralExpression::JsStringLiteralExpression( make::js_string_literal_expression(if ctx.as_preferred_quote().is_double() { - make::js_string_literal(&state.expected_value) + make::js_string_literal(&expected_value) } else { - make::js_string_literal_single_quotes(&state.expected_value) + make::js_string_literal_single_quotes(&expected_value) }), ), ), @@ -115,8 +118,7 @@ declare_node_union! { } pub struct CaseMismatchInfo { - expected_case: ExpectedStringCase, - expected_value: String, + expected_case: StringCase, call: JsCallExpression, literal: AnyJsExpression, } @@ -155,29 +157,26 @@ impl CaseMismatchInfo { } fn compare_call_with_literal(call: JsCallExpression, literal: AnyJsExpression) -> Option { - let expected_case = ExpectedStringCase::from_call(&call)?; - let static_value = literal.as_static_value()?; - let literal_value = static_value.text(); - let expected_value = expected_case.convert(literal_value); - if literal_value != expected_value { - Some(Self { - expected_case, - expected_value, - call, - literal, - }) - } else { - None - } + let expected_case = StringCase::from_call(&call)?; + let value = literal.as_static_value()?; + let literal_value = value.text(); + let mut case_iter = CharCaseIterator::from(literal_value); + let is_mismatch = case_iter.any(|case| case != expected_case); + is_mismatch.then_some(Self { + expected_case, + call, + literal, + }) } } -enum ExpectedStringCase { +#[derive(Debug, Eq, PartialEq)] +enum StringCase { Upper, Lower, } -impl ExpectedStringCase { +impl StringCase { fn from_call(call: &JsCallExpression) -> Option { if call.arguments().ok()?.args().len() != 0 { return None; @@ -197,15 +196,66 @@ impl ExpectedStringCase { fn convert(&self, s: &str) -> String { match self { - ExpectedStringCase::Upper => s.to_uppercase(), - ExpectedStringCase::Lower => s.to_lowercase(), + StringCase::Upper => s.to_uppercase(), + StringCase::Lower => s.to_lowercase(), } } fn description(&self) -> &str { match self { - ExpectedStringCase::Upper => "upper case", - ExpectedStringCase::Lower => "lower case", + StringCase::Upper => "upper case", + StringCase::Lower => "lower case", } } } + +struct CharCaseIterator<'a> { + iter: std::str::Chars<'a>, +} +impl<'a> CharCaseIterator<'a> { + fn from(s: &'a str) -> Self { + CharCaseIterator { iter: s.chars() } + } +} +impl<'a> Iterator for CharCaseIterator<'a> { + type Item = StringCase; + fn next(&mut self) -> Option { + while let Some(c) = self.iter.next() { + match c { + '\\' => { + match self.iter.next()? { + 'x' => { + // \xHH + self.iter.next(); + self.iter.next(); + } + 'u' => { + if self.iter.next()? == '{' { + // \u{H}, \u{HH}, ..., \u{HHHHHH} + while self.iter.next()? != '}' {} + } else { + // \uHHHH + self.iter.next(); + self.iter.next(); + self.iter.next(); + self.iter.next(); + } + } + _ => { + // \n, ... + self.iter.next(); + } + } + } + c => { + if c.is_uppercase() { + return Some(StringCase::Upper); + } else if c.is_lowercase() { + return Some(StringCase::Lower); + } + } + } + } + None + } +} diff --git a/crates/biome_js_analyze/tests/specs/correctness/noStringCaseMismatch/invalid.js b/crates/biome_js_analyze/tests/specs/correctness/noStringCaseMismatch/invalid.js new file mode 100644 index 000000000000..639bbdc619c8 --- /dev/null +++ b/crates/biome_js_analyze/tests/specs/correctness/noStringCaseMismatch/invalid.js @@ -0,0 +1,21 @@ +s.toUpperCase() === 'abc'; +s.toUpperCase() == 'abc'; +'abc' === s.toUpperCase(); +s.toLowerCase() === "\u001aX"; +s.toLowerCase() === "\u{001a}X"; +s.toLowerCase() === "\xaaX"; +s.toLowerCase() === "\nX"; + +if (s.toUpperCase() === 'abc' && c == d && e == f) {}; +while (s.toUpperCase() === 'abc' && c == d && e == f) {}; +while (s.toUpperCase() === 'abc') {}; +let b = s.toLowerCase() === `eFg`;; +do {} while (s.toLowerCase() === 'ABC');; +for (; s.toLowerCase() === 'ABC'; ) {}; + +switch (s.toUpperCase()) { case 'ABC': case 'abc': case 'aBc': default: } + +for (; s['toLowerCase']() === 'ABC'; ) {} +for (; s[`toUpperCase`]() === 'abc'; ) {} + +switch (s['toLowerCase']()) { case 'Abc': case 'aBc': case 'abC': default: } diff --git a/crates/biome_js_analyze/tests/specs/correctness/noStringCaseMismatch/invalid.js.snap b/crates/biome_js_analyze/tests/specs/correctness/noStringCaseMismatch/invalid.js.snap new file mode 100644 index 000000000000..a3c8958fd6d9 --- /dev/null +++ b/crates/biome_js_analyze/tests/specs/correctness/noStringCaseMismatch/invalid.js.snap @@ -0,0 +1,756 @@ +--- +source: crates/biome_js_analyze/tests/spec_tests.rs +expression: invalid.js +--- +# Input +```jsx +s.toUpperCase() === 'abc'; +s.toUpperCase() == 'abc'; +'abc' === s.toUpperCase(); +s.toLowerCase() === "\u001aX"; +s.toLowerCase() === "\u{001a}X"; +s.toLowerCase() === "\xaaX"; +s.toLowerCase() === "\nX"; + +if (s.toUpperCase() === 'abc' && c == d && e == f) {}; +while (s.toUpperCase() === 'abc' && c == d && e == f) {}; +while (s.toUpperCase() === 'abc') {}; +let b = s.toLowerCase() === `eFg`;; +do {} while (s.toLowerCase() === 'ABC');; +for (; s.toLowerCase() === 'ABC'; ) {}; + +switch (s.toUpperCase()) { case 'ABC': case 'abc': case 'aBc': default: } + +for (; s['toLowerCase']() === 'ABC'; ) {} +for (; s[`toUpperCase`]() === 'abc'; ) {} + +switch (s['toLowerCase']()) { case 'Abc': case 'aBc': case 'abC': default: } + +``` + +# Diagnostics +``` +invalid.js:1:1 lint/correctness/noStringCaseMismatch FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! This expression always returns false. + + > 1 │ s.toUpperCase() === 'abc'; + │ ^^^^^^^^^^^^^^^^^^^^^^^^^ + 2 │ s.toUpperCase() == 'abc'; + 3 │ 'abc' === s.toUpperCase(); + + i This call convert the string to upper case + + > 1 │ s.toUpperCase() === 'abc'; + │ ^^^^^^^^^^^^^^^ + 2 │ s.toUpperCase() == 'abc'; + 3 │ 'abc' === s.toUpperCase(); + + i ... but this value is not in upper case + + > 1 │ s.toUpperCase() === 'abc'; + │ ^^^^^ + 2 │ s.toUpperCase() == 'abc'; + 3 │ 'abc' === s.toUpperCase(); + + i Unsafe fix: Use upper case string value. + + 1 │ - s.toUpperCase()·===·'abc'; + 1 │ + s.toUpperCase()·===·"ABC"; + 2 2 │ s.toUpperCase() == 'abc'; + 3 3 │ 'abc' === s.toUpperCase(); + + +``` + +``` +invalid.js:2:1 lint/correctness/noStringCaseMismatch FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! This expression always returns false. + + 1 │ s.toUpperCase() === 'abc'; + > 2 │ s.toUpperCase() == 'abc'; + │ ^^^^^^^^^^^^^^^^^^^^^^^^ + 3 │ 'abc' === s.toUpperCase(); + 4 │ s.toLowerCase() === "\u001aX"; + + i This call convert the string to upper case + + 1 │ s.toUpperCase() === 'abc'; + > 2 │ s.toUpperCase() == 'abc'; + │ ^^^^^^^^^^^^^^^ + 3 │ 'abc' === s.toUpperCase(); + 4 │ s.toLowerCase() === "\u001aX"; + + i ... but this value is not in upper case + + 1 │ s.toUpperCase() === 'abc'; + > 2 │ s.toUpperCase() == 'abc'; + │ ^^^^^ + 3 │ 'abc' === s.toUpperCase(); + 4 │ s.toLowerCase() === "\u001aX"; + + i Unsafe fix: Use upper case string value. + + 1 1 │ s.toUpperCase() === 'abc'; + 2 │ - s.toUpperCase()·==·'abc'; + 2 │ + s.toUpperCase()·==·"ABC"; + 3 3 │ 'abc' === s.toUpperCase(); + 4 4 │ s.toLowerCase() === "\u001aX"; + + +``` + +``` +invalid.js:3:1 lint/correctness/noStringCaseMismatch FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! This expression always returns false. + + 1 │ s.toUpperCase() === 'abc'; + 2 │ s.toUpperCase() == 'abc'; + > 3 │ 'abc' === s.toUpperCase(); + │ ^^^^^^^^^^^^^^^^^^^^^^^^^ + 4 │ s.toLowerCase() === "\u001aX"; + 5 │ s.toLowerCase() === "\u{001a}X"; + + i This call convert the string to upper case + + 1 │ s.toUpperCase() === 'abc'; + 2 │ s.toUpperCase() == 'abc'; + > 3 │ 'abc' === s.toUpperCase(); + │ ^^^^^^^^^^^^^^^ + 4 │ s.toLowerCase() === "\u001aX"; + 5 │ s.toLowerCase() === "\u{001a}X"; + + i ... but this value is not in upper case + + 1 │ s.toUpperCase() === 'abc'; + 2 │ s.toUpperCase() == 'abc'; + > 3 │ 'abc' === s.toUpperCase(); + │ ^^^^^ + 4 │ s.toLowerCase() === "\u001aX"; + 5 │ s.toLowerCase() === "\u{001a}X"; + + i Unsafe fix: Use upper case string value. + + 1 1 │ s.toUpperCase() === 'abc'; + 2 2 │ s.toUpperCase() == 'abc'; + 3 │ - 'abc'·===·s.toUpperCase(); + 3 │ + "ABC"·===·s.toUpperCase(); + 4 4 │ s.toLowerCase() === "\u001aX"; + 5 5 │ s.toLowerCase() === "\u{001a}X"; + + +``` + +``` +invalid.js:5:1 lint/correctness/noStringCaseMismatch FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! This expression always returns false. + + 3 │ 'abc' === s.toUpperCase(); + 4 │ s.toLowerCase() === "\u001aX"; + > 5 │ s.toLowerCase() === "\u{001a}X"; + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 6 │ s.toLowerCase() === "\xaaX"; + 7 │ s.toLowerCase() === "\nX"; + + i This call convert the string to lower case + + 3 │ 'abc' === s.toUpperCase(); + 4 │ s.toLowerCase() === "\u001aX"; + > 5 │ s.toLowerCase() === "\u{001a}X"; + │ ^^^^^^^^^^^^^^^ + 6 │ s.toLowerCase() === "\xaaX"; + 7 │ s.toLowerCase() === "\nX"; + + i ... but this value is not in lower case + + 3 │ 'abc' === s.toUpperCase(); + 4 │ s.toLowerCase() === "\u001aX"; + > 5 │ s.toLowerCase() === "\u{001a}X"; + │ ^^^^^^^^^^^ + 6 │ s.toLowerCase() === "\xaaX"; + 7 │ s.toLowerCase() === "\nX"; + + i Unsafe fix: Use lower case string value. + + 3 3 │ 'abc' === s.toUpperCase(); + 4 4 │ s.toLowerCase() === "\u001aX"; + 5 │ - s.toLowerCase()·===·"\u{001a}X"; + 5 │ + s.toLowerCase()·===·"\u{001a}x"; + 6 6 │ s.toLowerCase() === "\xaaX"; + 7 7 │ s.toLowerCase() === "\nX"; + + +``` + +``` +invalid.js:6:1 lint/correctness/noStringCaseMismatch FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! This expression always returns false. + + 4 │ s.toLowerCase() === "\u001aX"; + 5 │ s.toLowerCase() === "\u{001a}X"; + > 6 │ s.toLowerCase() === "\xaaX"; + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 7 │ s.toLowerCase() === "\nX"; + 8 │ + + i This call convert the string to lower case + + 4 │ s.toLowerCase() === "\u001aX"; + 5 │ s.toLowerCase() === "\u{001a}X"; + > 6 │ s.toLowerCase() === "\xaaX"; + │ ^^^^^^^^^^^^^^^ + 7 │ s.toLowerCase() === "\nX"; + 8 │ + + i ... but this value is not in lower case + + 4 │ s.toLowerCase() === "\u001aX"; + 5 │ s.toLowerCase() === "\u{001a}X"; + > 6 │ s.toLowerCase() === "\xaaX"; + │ ^^^^^^^ + 7 │ s.toLowerCase() === "\nX"; + 8 │ + + i Unsafe fix: Use lower case string value. + + 4 4 │ s.toLowerCase() === "\u001aX"; + 5 5 │ s.toLowerCase() === "\u{001a}X"; + 6 │ - s.toLowerCase()·===·"\xaaX"; + 6 │ + s.toLowerCase()·===·"\xaax"; + 7 7 │ s.toLowerCase() === "\nX"; + 8 8 │ + + +``` + +``` +invalid.js:9:5 lint/correctness/noStringCaseMismatch FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! This expression always returns false. + + 7 │ s.toLowerCase() === "\nX"; + 8 │ + > 9 │ if (s.toUpperCase() === 'abc' && c == d && e == f) {}; + │ ^^^^^^^^^^^^^^^^^^^^^^^^^ + 10 │ while (s.toUpperCase() === 'abc' && c == d && e == f) {}; + 11 │ while (s.toUpperCase() === 'abc') {}; + + i This call convert the string to upper case + + 7 │ s.toLowerCase() === "\nX"; + 8 │ + > 9 │ if (s.toUpperCase() === 'abc' && c == d && e == f) {}; + │ ^^^^^^^^^^^^^^^ + 10 │ while (s.toUpperCase() === 'abc' && c == d && e == f) {}; + 11 │ while (s.toUpperCase() === 'abc') {}; + + i ... but this value is not in upper case + + 7 │ s.toLowerCase() === "\nX"; + 8 │ + > 9 │ if (s.toUpperCase() === 'abc' && c == d && e == f) {}; + │ ^^^^^ + 10 │ while (s.toUpperCase() === 'abc' && c == d && e == f) {}; + 11 │ while (s.toUpperCase() === 'abc') {}; + + i Unsafe fix: Use upper case string value. + + 7 7 │ s.toLowerCase() === "\nX"; + 8 8 │ + 9 │ - if·(s.toUpperCase()·===·'abc'·&&·c·==·d·&&·e·==·f)·{}; + 9 │ + if·(s.toUpperCase()·===·"ABC"·&&·c·==·d·&&·e·==·f)·{}; + 10 10 │ while (s.toUpperCase() === 'abc' && c == d && e == f) {}; + 11 11 │ while (s.toUpperCase() === 'abc') {}; + + +``` + +``` +invalid.js:10:8 lint/correctness/noStringCaseMismatch FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! This expression always returns false. + + 9 │ if (s.toUpperCase() === 'abc' && c == d && e == f) {}; + > 10 │ while (s.toUpperCase() === 'abc' && c == d && e == f) {}; + │ ^^^^^^^^^^^^^^^^^^^^^^^^^ + 11 │ while (s.toUpperCase() === 'abc') {}; + 12 │ let b = s.toLowerCase() === `eFg`;; + + i This call convert the string to upper case + + 9 │ if (s.toUpperCase() === 'abc' && c == d && e == f) {}; + > 10 │ while (s.toUpperCase() === 'abc' && c == d && e == f) {}; + │ ^^^^^^^^^^^^^^^ + 11 │ while (s.toUpperCase() === 'abc') {}; + 12 │ let b = s.toLowerCase() === `eFg`;; + + i ... but this value is not in upper case + + 9 │ if (s.toUpperCase() === 'abc' && c == d && e == f) {}; + > 10 │ while (s.toUpperCase() === 'abc' && c == d && e == f) {}; + │ ^^^^^ + 11 │ while (s.toUpperCase() === 'abc') {}; + 12 │ let b = s.toLowerCase() === `eFg`;; + + i Unsafe fix: Use upper case string value. + + 8 8 │ + 9 9 │ if (s.toUpperCase() === 'abc' && c == d && e == f) {}; + 10 │ - while·(s.toUpperCase()·===·'abc'·&&·c·==·d·&&·e·==·f)·{}; + 10 │ + while·(s.toUpperCase()·===·"ABC"·&&·c·==·d·&&·e·==·f)·{}; + 11 11 │ while (s.toUpperCase() === 'abc') {}; + 12 12 │ let b = s.toLowerCase() === `eFg`;; + + +``` + +``` +invalid.js:11:8 lint/correctness/noStringCaseMismatch FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! This expression always returns false. + + 9 │ if (s.toUpperCase() === 'abc' && c == d && e == f) {}; + 10 │ while (s.toUpperCase() === 'abc' && c == d && e == f) {}; + > 11 │ while (s.toUpperCase() === 'abc') {}; + │ ^^^^^^^^^^^^^^^^^^^^^^^^^ + 12 │ let b = s.toLowerCase() === `eFg`;; + 13 │ do {} while (s.toLowerCase() === 'ABC');; + + i This call convert the string to upper case + + 9 │ if (s.toUpperCase() === 'abc' && c == d && e == f) {}; + 10 │ while (s.toUpperCase() === 'abc' && c == d && e == f) {}; + > 11 │ while (s.toUpperCase() === 'abc') {}; + │ ^^^^^^^^^^^^^^^ + 12 │ let b = s.toLowerCase() === `eFg`;; + 13 │ do {} while (s.toLowerCase() === 'ABC');; + + i ... but this value is not in upper case + + 9 │ if (s.toUpperCase() === 'abc' && c == d && e == f) {}; + 10 │ while (s.toUpperCase() === 'abc' && c == d && e == f) {}; + > 11 │ while (s.toUpperCase() === 'abc') {}; + │ ^^^^^ + 12 │ let b = s.toLowerCase() === `eFg`;; + 13 │ do {} while (s.toLowerCase() === 'ABC');; + + i Unsafe fix: Use upper case string value. + + 9 9 │ if (s.toUpperCase() === 'abc' && c == d && e == f) {}; + 10 10 │ while (s.toUpperCase() === 'abc' && c == d && e == f) {}; + 11 │ - while·(s.toUpperCase()·===·'abc')·{}; + 11 │ + while·(s.toUpperCase()·===·"ABC")·{}; + 12 12 │ let b = s.toLowerCase() === `eFg`;; + 13 13 │ do {} while (s.toLowerCase() === 'ABC');; + + +``` + +``` +invalid.js:12:9 lint/correctness/noStringCaseMismatch FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! This expression always returns false. + + 10 │ while (s.toUpperCase() === 'abc' && c == d && e == f) {}; + 11 │ while (s.toUpperCase() === 'abc') {}; + > 12 │ let b = s.toLowerCase() === `eFg`;; + │ ^^^^^^^^^^^^^^^^^^^^^^^^^ + 13 │ do {} while (s.toLowerCase() === 'ABC');; + 14 │ for (; s.toLowerCase() === 'ABC'; ) {}; + + i This call convert the string to lower case + + 10 │ while (s.toUpperCase() === 'abc' && c == d && e == f) {}; + 11 │ while (s.toUpperCase() === 'abc') {}; + > 12 │ let b = s.toLowerCase() === `eFg`;; + │ ^^^^^^^^^^^^^^^ + 13 │ do {} while (s.toLowerCase() === 'ABC');; + 14 │ for (; s.toLowerCase() === 'ABC'; ) {}; + + i ... but this value is not in lower case + + 10 │ while (s.toUpperCase() === 'abc' && c == d && e == f) {}; + 11 │ while (s.toUpperCase() === 'abc') {}; + > 12 │ let b = s.toLowerCase() === `eFg`;; + │ ^^^^^ + 13 │ do {} while (s.toLowerCase() === 'ABC');; + 14 │ for (; s.toLowerCase() === 'ABC'; ) {}; + + i Unsafe fix: Use lower case string value. + + 10 10 │ while (s.toUpperCase() === 'abc' && c == d && e == f) {}; + 11 11 │ while (s.toUpperCase() === 'abc') {}; + 12 │ - let·b·=·s.toLowerCase()·===·`eFg`;; + 12 │ + let·b·=·s.toLowerCase()·===·"efg";; + 13 13 │ do {} while (s.toLowerCase() === 'ABC');; + 14 14 │ for (; s.toLowerCase() === 'ABC'; ) {}; + + +``` + +``` +invalid.js:13:14 lint/correctness/noStringCaseMismatch FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! This expression always returns false. + + 11 │ while (s.toUpperCase() === 'abc') {}; + 12 │ let b = s.toLowerCase() === `eFg`;; + > 13 │ do {} while (s.toLowerCase() === 'ABC');; + │ ^^^^^^^^^^^^^^^^^^^^^^^^^ + 14 │ for (; s.toLowerCase() === 'ABC'; ) {}; + 15 │ + + i This call convert the string to lower case + + 11 │ while (s.toUpperCase() === 'abc') {}; + 12 │ let b = s.toLowerCase() === `eFg`;; + > 13 │ do {} while (s.toLowerCase() === 'ABC');; + │ ^^^^^^^^^^^^^^^ + 14 │ for (; s.toLowerCase() === 'ABC'; ) {}; + 15 │ + + i ... but this value is not in lower case + + 11 │ while (s.toUpperCase() === 'abc') {}; + 12 │ let b = s.toLowerCase() === `eFg`;; + > 13 │ do {} while (s.toLowerCase() === 'ABC');; + │ ^^^^^ + 14 │ for (; s.toLowerCase() === 'ABC'; ) {}; + 15 │ + + i Unsafe fix: Use lower case string value. + + 11 11 │ while (s.toUpperCase() === 'abc') {}; + 12 12 │ let b = s.toLowerCase() === `eFg`;; + 13 │ - do·{}·while·(s.toLowerCase()·===·'ABC');; + 13 │ + do·{}·while·(s.toLowerCase()·===·"abc");; + 14 14 │ for (; s.toLowerCase() === 'ABC'; ) {}; + 15 15 │ + + +``` + +``` +invalid.js:14:8 lint/correctness/noStringCaseMismatch FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! This expression always returns false. + + 12 │ let b = s.toLowerCase() === `eFg`;; + 13 │ do {} while (s.toLowerCase() === 'ABC');; + > 14 │ for (; s.toLowerCase() === 'ABC'; ) {}; + │ ^^^^^^^^^^^^^^^^^^^^^^^^^ + 15 │ + 16 │ switch (s.toUpperCase()) { case 'ABC': case 'abc': case 'aBc': default: } + + i This call convert the string to lower case + + 12 │ let b = s.toLowerCase() === `eFg`;; + 13 │ do {} while (s.toLowerCase() === 'ABC');; + > 14 │ for (; s.toLowerCase() === 'ABC'; ) {}; + │ ^^^^^^^^^^^^^^^ + 15 │ + 16 │ switch (s.toUpperCase()) { case 'ABC': case 'abc': case 'aBc': default: } + + i ... but this value is not in lower case + + 12 │ let b = s.toLowerCase() === `eFg`;; + 13 │ do {} while (s.toLowerCase() === 'ABC');; + > 14 │ for (; s.toLowerCase() === 'ABC'; ) {}; + │ ^^^^^ + 15 │ + 16 │ switch (s.toUpperCase()) { case 'ABC': case 'abc': case 'aBc': default: } + + i Unsafe fix: Use lower case string value. + + 12 12 │ let b = s.toLowerCase() === `eFg`;; + 13 13 │ do {} while (s.toLowerCase() === 'ABC');; + 14 │ - for·(;·s.toLowerCase()·===·'ABC';·)·{}; + 14 │ + for·(;·s.toLowerCase()·===·"abc";·)·{}; + 15 15 │ + 16 16 │ switch (s.toUpperCase()) { case 'ABC': case 'abc': case 'aBc': default: } + + +``` + +``` +invalid.js:16:45 lint/correctness/noStringCaseMismatch FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! This case will never match. + + 14 │ for (; s.toLowerCase() === 'ABC'; ) {}; + 15 │ + > 16 │ switch (s.toUpperCase()) { case 'ABC': case 'abc': case 'aBc': default: } + │ ^^^^^ + 17 │ + 18 │ for (; s['toLowerCase']() === 'ABC'; ) {} + + i This call convert the string to upper case + + 14 │ for (; s.toLowerCase() === 'ABC'; ) {}; + 15 │ + > 16 │ switch (s.toUpperCase()) { case 'ABC': case 'abc': case 'aBc': default: } + │ ^^^^^^^^^^^^^^^ + 17 │ + 18 │ for (; s['toLowerCase']() === 'ABC'; ) {} + + i ... but this value is not in upper case + + 14 │ for (; s.toLowerCase() === 'ABC'; ) {}; + 15 │ + > 16 │ switch (s.toUpperCase()) { case 'ABC': case 'abc': case 'aBc': default: } + │ ^^^^^ + 17 │ + 18 │ for (; s['toLowerCase']() === 'ABC'; ) {} + + i Unsafe fix: Use upper case string value. + + 14 14 │ for (; s.toLowerCase() === 'ABC'; ) {}; + 15 15 │ + 16 │ - switch·(s.toUpperCase())·{·case·'ABC':·case·'abc':·case·'aBc':·default:·} + 16 │ + switch·(s.toUpperCase())·{·case·'ABC':·case·"ABC":·case·'aBc':·default:·} + 17 17 │ + 18 18 │ for (; s['toLowerCase']() === 'ABC'; ) {} + + +``` + +``` +invalid.js:16:57 lint/correctness/noStringCaseMismatch FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! This case will never match. + + 14 │ for (; s.toLowerCase() === 'ABC'; ) {}; + 15 │ + > 16 │ switch (s.toUpperCase()) { case 'ABC': case 'abc': case 'aBc': default: } + │ ^^^^^ + 17 │ + 18 │ for (; s['toLowerCase']() === 'ABC'; ) {} + + i This call convert the string to upper case + + 14 │ for (; s.toLowerCase() === 'ABC'; ) {}; + 15 │ + > 16 │ switch (s.toUpperCase()) { case 'ABC': case 'abc': case 'aBc': default: } + │ ^^^^^^^^^^^^^^^ + 17 │ + 18 │ for (; s['toLowerCase']() === 'ABC'; ) {} + + i ... but this value is not in upper case + + 14 │ for (; s.toLowerCase() === 'ABC'; ) {}; + 15 │ + > 16 │ switch (s.toUpperCase()) { case 'ABC': case 'abc': case 'aBc': default: } + │ ^^^^^ + 17 │ + 18 │ for (; s['toLowerCase']() === 'ABC'; ) {} + + i Unsafe fix: Use upper case string value. + + 14 14 │ for (; s.toLowerCase() === 'ABC'; ) {}; + 15 15 │ + 16 │ - switch·(s.toUpperCase())·{·case·'ABC':·case·'abc':·case·'aBc':·default:·} + 16 │ + switch·(s.toUpperCase())·{·case·'ABC':·case·'abc':·case·"ABC":·default:·} + 17 17 │ + 18 18 │ for (; s['toLowerCase']() === 'ABC'; ) {} + + +``` + +``` +invalid.js:18:8 lint/correctness/noStringCaseMismatch FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! This expression always returns false. + + 16 │ switch (s.toUpperCase()) { case 'ABC': case 'abc': case 'aBc': default: } + 17 │ + > 18 │ for (; s['toLowerCase']() === 'ABC'; ) {} + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 19 │ for (; s[`toUpperCase`]() === 'abc'; ) {} + 20 │ + + i This call convert the string to lower case + + 16 │ switch (s.toUpperCase()) { case 'ABC': case 'abc': case 'aBc': default: } + 17 │ + > 18 │ for (; s['toLowerCase']() === 'ABC'; ) {} + │ ^^^^^^^^^^^^^^^^^^ + 19 │ for (; s[`toUpperCase`]() === 'abc'; ) {} + 20 │ + + i ... but this value is not in lower case + + 16 │ switch (s.toUpperCase()) { case 'ABC': case 'abc': case 'aBc': default: } + 17 │ + > 18 │ for (; s['toLowerCase']() === 'ABC'; ) {} + │ ^^^^^ + 19 │ for (; s[`toUpperCase`]() === 'abc'; ) {} + 20 │ + + i Unsafe fix: Use lower case string value. + + 16 16 │ switch (s.toUpperCase()) { case 'ABC': case 'abc': case 'aBc': default: } + 17 17 │ + 18 │ - for·(;·s['toLowerCase']()·===·'ABC';·)·{} + 18 │ + for·(;·s['toLowerCase']()·===·"abc";·)·{} + 19 19 │ for (; s[`toUpperCase`]() === 'abc'; ) {} + 20 20 │ + + +``` + +``` +invalid.js:19:8 lint/correctness/noStringCaseMismatch FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! This expression always returns false. + + 18 │ for (; s['toLowerCase']() === 'ABC'; ) {} + > 19 │ for (; s[`toUpperCase`]() === 'abc'; ) {} + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 20 │ + 21 │ switch (s['toLowerCase']()) { case 'Abc': case 'aBc': case 'abC': default: } + + i This call convert the string to upper case + + 18 │ for (; s['toLowerCase']() === 'ABC'; ) {} + > 19 │ for (; s[`toUpperCase`]() === 'abc'; ) {} + │ ^^^^^^^^^^^^^^^^^^ + 20 │ + 21 │ switch (s['toLowerCase']()) { case 'Abc': case 'aBc': case 'abC': default: } + + i ... but this value is not in upper case + + 18 │ for (; s['toLowerCase']() === 'ABC'; ) {} + > 19 │ for (; s[`toUpperCase`]() === 'abc'; ) {} + │ ^^^^^ + 20 │ + 21 │ switch (s['toLowerCase']()) { case 'Abc': case 'aBc': case 'abC': default: } + + i Unsafe fix: Use upper case string value. + + 17 17 │ + 18 18 │ for (; s['toLowerCase']() === 'ABC'; ) {} + 19 │ - for·(;·s[`toUpperCase`]()·===·'abc';·)·{} + 19 │ + for·(;·s[`toUpperCase`]()·===·"ABC";·)·{} + 20 20 │ + 21 21 │ switch (s['toLowerCase']()) { case 'Abc': case 'aBc': case 'abC': default: } + + +``` + +``` +invalid.js:21:36 lint/correctness/noStringCaseMismatch FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! This case will never match. + + 19 │ for (; s[`toUpperCase`]() === 'abc'; ) {} + 20 │ + > 21 │ switch (s['toLowerCase']()) { case 'Abc': case 'aBc': case 'abC': default: } + │ ^^^^^ + 22 │ + + i This call convert the string to lower case + + 19 │ for (; s[`toUpperCase`]() === 'abc'; ) {} + 20 │ + > 21 │ switch (s['toLowerCase']()) { case 'Abc': case 'aBc': case 'abC': default: } + │ ^^^^^^^^^^^^^^^^^^ + 22 │ + + i ... but this value is not in lower case + + 19 │ for (; s[`toUpperCase`]() === 'abc'; ) {} + 20 │ + > 21 │ switch (s['toLowerCase']()) { case 'Abc': case 'aBc': case 'abC': default: } + │ ^^^^^ + 22 │ + + i Unsafe fix: Use lower case string value. + + 19 19 │ for (; s[`toUpperCase`]() === 'abc'; ) {} + 20 20 │ + 21 │ - switch·(s['toLowerCase']())·{·case·'Abc':·case·'aBc':·case·'abC':·default:·} + 21 │ + switch·(s['toLowerCase']())·{·case·"abc":·case·'aBc':·case·'abC':·default:·} + 22 22 │ + + +``` + +``` +invalid.js:21:48 lint/correctness/noStringCaseMismatch FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! This case will never match. + + 19 │ for (; s[`toUpperCase`]() === 'abc'; ) {} + 20 │ + > 21 │ switch (s['toLowerCase']()) { case 'Abc': case 'aBc': case 'abC': default: } + │ ^^^^^ + 22 │ + + i This call convert the string to lower case + + 19 │ for (; s[`toUpperCase`]() === 'abc'; ) {} + 20 │ + > 21 │ switch (s['toLowerCase']()) { case 'Abc': case 'aBc': case 'abC': default: } + │ ^^^^^^^^^^^^^^^^^^ + 22 │ + + i ... but this value is not in lower case + + 19 │ for (; s[`toUpperCase`]() === 'abc'; ) {} + 20 │ + > 21 │ switch (s['toLowerCase']()) { case 'Abc': case 'aBc': case 'abC': default: } + │ ^^^^^ + 22 │ + + i Unsafe fix: Use lower case string value. + + 19 19 │ for (; s[`toUpperCase`]() === 'abc'; ) {} + 20 20 │ + 21 │ - switch·(s['toLowerCase']())·{·case·'Abc':·case·'aBc':·case·'abC':·default:·} + 21 │ + switch·(s['toLowerCase']())·{·case·'Abc':·case·"abc":·case·'abC':·default:·} + 22 22 │ + + +``` + +``` +invalid.js:21:60 lint/correctness/noStringCaseMismatch FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! This case will never match. + + 19 │ for (; s[`toUpperCase`]() === 'abc'; ) {} + 20 │ + > 21 │ switch (s['toLowerCase']()) { case 'Abc': case 'aBc': case 'abC': default: } + │ ^^^^^ + 22 │ + + i This call convert the string to lower case + + 19 │ for (; s[`toUpperCase`]() === 'abc'; ) {} + 20 │ + > 21 │ switch (s['toLowerCase']()) { case 'Abc': case 'aBc': case 'abC': default: } + │ ^^^^^^^^^^^^^^^^^^ + 22 │ + + i ... but this value is not in lower case + + 19 │ for (; s[`toUpperCase`]() === 'abc'; ) {} + 20 │ + > 21 │ switch (s['toLowerCase']()) { case 'Abc': case 'aBc': case 'abC': default: } + │ ^^^^^ + 22 │ + + i Unsafe fix: Use lower case string value. + + 19 19 │ for (; s[`toUpperCase`]() === 'abc'; ) {} + 20 20 │ + 21 │ - switch·(s['toLowerCase']())·{·case·'Abc':·case·'aBc':·case·'abC':·default:·} + 21 │ + switch·(s['toLowerCase']())·{·case·'Abc':·case·'aBc':·case·"abc":·default:·} + 22 22 │ + + +``` diff --git a/crates/biome_js_analyze/tests/specs/correctness/noStringCaseMismatch/invalid.jsonc b/crates/biome_js_analyze/tests/specs/correctness/noStringCaseMismatch/invalid.jsonc deleted file mode 100644 index ff54dab090ee..000000000000 --- a/crates/biome_js_analyze/tests/specs/correctness/noStringCaseMismatch/invalid.jsonc +++ /dev/null @@ -1,18 +0,0 @@ -[ - "const a = s.toUpperCase() === 'abc';", - "const c = s.toUpperCase() == 'abc';", - "const a2 = 'abc' === s.toUpperCase();", - "if (s.toUpperCase() === 'abc' && c == d && e == f) {}", - "while (s.toUpperCase() === 'abc' && c == d && e == f) {}", - "while (s.toUpperCase() === 'abc') {}", - "let b = s.toLowerCase() === `eFg`;", - "do {} while (s.toLowerCase() === 'ABC');", - "for (; s.toLowerCase() === 'ABC'; ) {}", - - "switch (s.toUpperCase()) { case 'ABC': case 'abc': case 'aBc': default: }", - - "for (; s['toLowerCase']() === 'ABC'; ) {}", - "for (; s[`toUpperCase`]() === 'abc'; ) {}", - - "switch (s['toLowerCase']()) { case 'Abc': case 'aBc': case 'abC': default: }" -] diff --git a/crates/biome_js_analyze/tests/specs/correctness/noStringCaseMismatch/invalid.jsonc.snap b/crates/biome_js_analyze/tests/specs/correctness/noStringCaseMismatch/invalid.jsonc.snap deleted file mode 100644 index 5ebaac2497e9..000000000000 --- a/crates/biome_js_analyze/tests/specs/correctness/noStringCaseMismatch/invalid.jsonc.snap +++ /dev/null @@ -1,499 +0,0 @@ ---- -source: crates/biome_js_analyze/tests/spec_tests.rs -expression: invalid.jsonc ---- -# Input -```cjs -const a = s.toUpperCase() === 'abc'; -``` - -# Diagnostics -``` -invalid.jsonc:1:11 lint/correctness/noStringCaseMismatch FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! This expression always returns false. - - > 1 │ const a = s.toUpperCase() === 'abc'; - │ ^^^^^^^^^^^^^^^^^^^^^^^^^ - - i This call convert the string to upper case - - > 1 │ const a = s.toUpperCase() === 'abc'; - │ ^^^^^^^^^^^^^^^ - - i ... but this value is not in upper case - - > 1 │ const a = s.toUpperCase() === 'abc'; - │ ^^^^^ - - i Unsafe fix: Use upper case string value. - - - const·a·=·s.toUpperCase()·===·'abc'; - + const·a·=·s.toUpperCase()·===·"ABC"; - - -``` - -# Input -```cjs -const c = s.toUpperCase() == 'abc'; -``` - -# Diagnostics -``` -invalid.jsonc:1:11 lint/correctness/noStringCaseMismatch FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! This expression always returns false. - - > 1 │ const c = s.toUpperCase() == 'abc'; - │ ^^^^^^^^^^^^^^^^^^^^^^^^ - - i This call convert the string to upper case - - > 1 │ const c = s.toUpperCase() == 'abc'; - │ ^^^^^^^^^^^^^^^ - - i ... but this value is not in upper case - - > 1 │ const c = s.toUpperCase() == 'abc'; - │ ^^^^^ - - i Unsafe fix: Use upper case string value. - - - const·c·=·s.toUpperCase()·==·'abc'; - + const·c·=·s.toUpperCase()·==·"ABC"; - - -``` - -# Input -```cjs -const a2 = 'abc' === s.toUpperCase(); -``` - -# Diagnostics -``` -invalid.jsonc:1:12 lint/correctness/noStringCaseMismatch FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! This expression always returns false. - - > 1 │ const a2 = 'abc' === s.toUpperCase(); - │ ^^^^^^^^^^^^^^^^^^^^^^^^^ - - i This call convert the string to upper case - - > 1 │ const a2 = 'abc' === s.toUpperCase(); - │ ^^^^^^^^^^^^^^^ - - i ... but this value is not in upper case - - > 1 │ const a2 = 'abc' === s.toUpperCase(); - │ ^^^^^ - - i Unsafe fix: Use upper case string value. - - - const·a2·=·'abc'·===·s.toUpperCase(); - + const·a2·=·"ABC"·===·s.toUpperCase(); - - -``` - -# Input -```cjs -if (s.toUpperCase() === 'abc' && c == d && e == f) {} -``` - -# Diagnostics -``` -invalid.jsonc:1:5 lint/correctness/noStringCaseMismatch FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! This expression always returns false. - - > 1 │ if (s.toUpperCase() === 'abc' && c == d && e == f) {} - │ ^^^^^^^^^^^^^^^^^^^^^^^^^ - - i This call convert the string to upper case - - > 1 │ if (s.toUpperCase() === 'abc' && c == d && e == f) {} - │ ^^^^^^^^^^^^^^^ - - i ... but this value is not in upper case - - > 1 │ if (s.toUpperCase() === 'abc' && c == d && e == f) {} - │ ^^^^^ - - i Unsafe fix: Use upper case string value. - - - if·(s.toUpperCase()·===·'abc'·&&·c·==·d·&&·e·==·f)·{} - + if·(s.toUpperCase()·===·"ABC"·&&·c·==·d·&&·e·==·f)·{} - - -``` - -# Input -```cjs -while (s.toUpperCase() === 'abc' && c == d && e == f) {} -``` - -# Diagnostics -``` -invalid.jsonc:1:8 lint/correctness/noStringCaseMismatch FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! This expression always returns false. - - > 1 │ while (s.toUpperCase() === 'abc' && c == d && e == f) {} - │ ^^^^^^^^^^^^^^^^^^^^^^^^^ - - i This call convert the string to upper case - - > 1 │ while (s.toUpperCase() === 'abc' && c == d && e == f) {} - │ ^^^^^^^^^^^^^^^ - - i ... but this value is not in upper case - - > 1 │ while (s.toUpperCase() === 'abc' && c == d && e == f) {} - │ ^^^^^ - - i Unsafe fix: Use upper case string value. - - - while·(s.toUpperCase()·===·'abc'·&&·c·==·d·&&·e·==·f)·{} - + while·(s.toUpperCase()·===·"ABC"·&&·c·==·d·&&·e·==·f)·{} - - -``` - -# Input -```cjs -while (s.toUpperCase() === 'abc') {} -``` - -# Diagnostics -``` -invalid.jsonc:1:8 lint/correctness/noStringCaseMismatch FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! This expression always returns false. - - > 1 │ while (s.toUpperCase() === 'abc') {} - │ ^^^^^^^^^^^^^^^^^^^^^^^^^ - - i This call convert the string to upper case - - > 1 │ while (s.toUpperCase() === 'abc') {} - │ ^^^^^^^^^^^^^^^ - - i ... but this value is not in upper case - - > 1 │ while (s.toUpperCase() === 'abc') {} - │ ^^^^^ - - i Unsafe fix: Use upper case string value. - - - while·(s.toUpperCase()·===·'abc')·{} - + while·(s.toUpperCase()·===·"ABC")·{} - - -``` - -# Input -```cjs -let b = s.toLowerCase() === `eFg`; -``` - -# Diagnostics -``` -invalid.jsonc:1:9 lint/correctness/noStringCaseMismatch FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! This expression always returns false. - - > 1 │ let b = s.toLowerCase() === `eFg`; - │ ^^^^^^^^^^^^^^^^^^^^^^^^^ - - i This call convert the string to lower case - - > 1 │ let b = s.toLowerCase() === `eFg`; - │ ^^^^^^^^^^^^^^^ - - i ... but this value is not in lower case - - > 1 │ let b = s.toLowerCase() === `eFg`; - │ ^^^^^ - - i Unsafe fix: Use lower case string value. - - - let·b·=·s.toLowerCase()·===·`eFg`; - + let·b·=·s.toLowerCase()·===·"efg"; - - -``` - -# Input -```cjs -do {} while (s.toLowerCase() === 'ABC'); -``` - -# Diagnostics -``` -invalid.jsonc:1:14 lint/correctness/noStringCaseMismatch FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! This expression always returns false. - - > 1 │ do {} while (s.toLowerCase() === 'ABC'); - │ ^^^^^^^^^^^^^^^^^^^^^^^^^ - - i This call convert the string to lower case - - > 1 │ do {} while (s.toLowerCase() === 'ABC'); - │ ^^^^^^^^^^^^^^^ - - i ... but this value is not in lower case - - > 1 │ do {} while (s.toLowerCase() === 'ABC'); - │ ^^^^^ - - i Unsafe fix: Use lower case string value. - - - do·{}·while·(s.toLowerCase()·===·'ABC'); - + do·{}·while·(s.toLowerCase()·===·"abc"); - - -``` - -# Input -```cjs -for (; s.toLowerCase() === 'ABC'; ) {} -``` - -# Diagnostics -``` -invalid.jsonc:1:8 lint/correctness/noStringCaseMismatch FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! This expression always returns false. - - > 1 │ for (; s.toLowerCase() === 'ABC'; ) {} - │ ^^^^^^^^^^^^^^^^^^^^^^^^^ - - i This call convert the string to lower case - - > 1 │ for (; s.toLowerCase() === 'ABC'; ) {} - │ ^^^^^^^^^^^^^^^ - - i ... but this value is not in lower case - - > 1 │ for (; s.toLowerCase() === 'ABC'; ) {} - │ ^^^^^ - - i Unsafe fix: Use lower case string value. - - - for·(;·s.toLowerCase()·===·'ABC';·)·{} - + for·(;·s.toLowerCase()·===·"abc";·)·{} - - -``` - -# Input -```cjs -switch (s.toUpperCase()) { case 'ABC': case 'abc': case 'aBc': default: } -``` - -# Diagnostics -``` -invalid.jsonc:1:45 lint/correctness/noStringCaseMismatch FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! This case will never match. - - > 1 │ switch (s.toUpperCase()) { case 'ABC': case 'abc': case 'aBc': default: } - │ ^^^^^ - - i This call convert the string to upper case - - > 1 │ switch (s.toUpperCase()) { case 'ABC': case 'abc': case 'aBc': default: } - │ ^^^^^^^^^^^^^^^ - - i ... but this value is not in upper case - - > 1 │ switch (s.toUpperCase()) { case 'ABC': case 'abc': case 'aBc': default: } - │ ^^^^^ - - i Unsafe fix: Use upper case string value. - - - switch·(s.toUpperCase())·{·case·'ABC':·case·'abc':·case·'aBc':·default:·} - + switch·(s.toUpperCase())·{·case·'ABC':·case·"ABC":·case·'aBc':·default:·} - - -``` - -``` -invalid.jsonc:1:57 lint/correctness/noStringCaseMismatch FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! This case will never match. - - > 1 │ switch (s.toUpperCase()) { case 'ABC': case 'abc': case 'aBc': default: } - │ ^^^^^ - - i This call convert the string to upper case - - > 1 │ switch (s.toUpperCase()) { case 'ABC': case 'abc': case 'aBc': default: } - │ ^^^^^^^^^^^^^^^ - - i ... but this value is not in upper case - - > 1 │ switch (s.toUpperCase()) { case 'ABC': case 'abc': case 'aBc': default: } - │ ^^^^^ - - i Unsafe fix: Use upper case string value. - - - switch·(s.toUpperCase())·{·case·'ABC':·case·'abc':·case·'aBc':·default:·} - + switch·(s.toUpperCase())·{·case·'ABC':·case·'abc':·case·"ABC":·default:·} - - -``` - -# Input -```cjs -for (; s['toLowerCase']() === 'ABC'; ) {} -``` - -# Diagnostics -``` -invalid.jsonc:1:8 lint/correctness/noStringCaseMismatch FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! This expression always returns false. - - > 1 │ for (; s['toLowerCase']() === 'ABC'; ) {} - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - i This call convert the string to lower case - - > 1 │ for (; s['toLowerCase']() === 'ABC'; ) {} - │ ^^^^^^^^^^^^^^^^^^ - - i ... but this value is not in lower case - - > 1 │ for (; s['toLowerCase']() === 'ABC'; ) {} - │ ^^^^^ - - i Unsafe fix: Use lower case string value. - - - for·(;·s['toLowerCase']()·===·'ABC';·)·{} - + for·(;·s['toLowerCase']()·===·"abc";·)·{} - - -``` - -# Input -```cjs -for (; s[`toUpperCase`]() === 'abc'; ) {} -``` - -# Diagnostics -``` -invalid.jsonc:1:8 lint/correctness/noStringCaseMismatch FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! This expression always returns false. - - > 1 │ for (; s[`toUpperCase`]() === 'abc'; ) {} - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - i This call convert the string to upper case - - > 1 │ for (; s[`toUpperCase`]() === 'abc'; ) {} - │ ^^^^^^^^^^^^^^^^^^ - - i ... but this value is not in upper case - - > 1 │ for (; s[`toUpperCase`]() === 'abc'; ) {} - │ ^^^^^ - - i Unsafe fix: Use upper case string value. - - - for·(;·s[`toUpperCase`]()·===·'abc';·)·{} - + for·(;·s[`toUpperCase`]()·===·"ABC";·)·{} - - -``` - -# Input -```cjs -switch (s['toLowerCase']()) { case 'Abc': case 'aBc': case 'abC': default: } -``` - -# Diagnostics -``` -invalid.jsonc:1:36 lint/correctness/noStringCaseMismatch FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! This case will never match. - - > 1 │ switch (s['toLowerCase']()) { case 'Abc': case 'aBc': case 'abC': default: } - │ ^^^^^ - - i This call convert the string to lower case - - > 1 │ switch (s['toLowerCase']()) { case 'Abc': case 'aBc': case 'abC': default: } - │ ^^^^^^^^^^^^^^^^^^ - - i ... but this value is not in lower case - - > 1 │ switch (s['toLowerCase']()) { case 'Abc': case 'aBc': case 'abC': default: } - │ ^^^^^ - - i Unsafe fix: Use lower case string value. - - - switch·(s['toLowerCase']())·{·case·'Abc':·case·'aBc':·case·'abC':·default:·} - + switch·(s['toLowerCase']())·{·case·"abc":·case·'aBc':·case·'abC':·default:·} - - -``` - -``` -invalid.jsonc:1:48 lint/correctness/noStringCaseMismatch FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! This case will never match. - - > 1 │ switch (s['toLowerCase']()) { case 'Abc': case 'aBc': case 'abC': default: } - │ ^^^^^ - - i This call convert the string to lower case - - > 1 │ switch (s['toLowerCase']()) { case 'Abc': case 'aBc': case 'abC': default: } - │ ^^^^^^^^^^^^^^^^^^ - - i ... but this value is not in lower case - - > 1 │ switch (s['toLowerCase']()) { case 'Abc': case 'aBc': case 'abC': default: } - │ ^^^^^ - - i Unsafe fix: Use lower case string value. - - - switch·(s['toLowerCase']())·{·case·'Abc':·case·'aBc':·case·'abC':·default:·} - + switch·(s['toLowerCase']())·{·case·'Abc':·case·"abc":·case·'abC':·default:·} - - -``` - -``` -invalid.jsonc:1:60 lint/correctness/noStringCaseMismatch FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! This case will never match. - - > 1 │ switch (s['toLowerCase']()) { case 'Abc': case 'aBc': case 'abC': default: } - │ ^^^^^ - - i This call convert the string to lower case - - > 1 │ switch (s['toLowerCase']()) { case 'Abc': case 'aBc': case 'abC': default: } - │ ^^^^^^^^^^^^^^^^^^ - - i ... but this value is not in lower case - - > 1 │ switch (s['toLowerCase']()) { case 'Abc': case 'aBc': case 'abC': default: } - │ ^^^^^ - - i Unsafe fix: Use lower case string value. - - - switch·(s['toLowerCase']())·{·case·'Abc':·case·'aBc':·case·'abC':·default:·} - + switch·(s['toLowerCase']())·{·case·'Abc':·case·'aBc':·case·"abc":·default:·} - - -``` - - diff --git a/crates/biome_js_analyze/tests/specs/correctness/noStringCaseMismatch/valid.js b/crates/biome_js_analyze/tests/specs/correctness/noStringCaseMismatch/valid.js new file mode 100644 index 000000000000..773f78b33832 --- /dev/null +++ b/crates/biome_js_analyze/tests/specs/correctness/noStringCaseMismatch/valid.js @@ -0,0 +1,16 @@ +s.toUpperCase() === 'ABC'; +s.toLowerCase() === 'abc'; +s.toUpperCase() === '20'; +s.toLowerCase() === '20'; +s.toLowerCase() === `eFg${12}`; +s.toLowerCase() == `eFg${12}`; +s.toLowerCase() === "\xaa"; +s.toLowerCase() === "\xAA"; +s.toUpperCase() === "\u001b"; +s.toLowerCase() === "\u001B"; +s.toUpperCase() === "\u000D"; +s.toLowerCase() === "\u000D"; +s.toLowerCase() === "\u{a}aa"; +s.toLowerCase() === "\u{A}aa"; +s.toUpperCase() === "{}"; +s.toLowerCase() === "{}"; \ No newline at end of file diff --git a/crates/biome_js_analyze/tests/specs/correctness/noStringCaseMismatch/valid.js.snap b/crates/biome_js_analyze/tests/specs/correctness/noStringCaseMismatch/valid.js.snap new file mode 100644 index 000000000000..d39ff825d25f --- /dev/null +++ b/crates/biome_js_analyze/tests/specs/correctness/noStringCaseMismatch/valid.js.snap @@ -0,0 +1,23 @@ +--- +source: crates/biome_js_analyze/tests/spec_tests.rs +expression: valid.js +--- +# Input +```jsx +s.toUpperCase() === 'ABC'; +s.toLowerCase() === 'abc'; +s.toUpperCase() === '20'; +s.toLowerCase() === '20'; +s.toLowerCase() === `eFg${12}`; +s.toLowerCase() == `eFg${12}`; +s.toLowerCase() === "\xaa"; +s.toLowerCase() === "\xAA"; +s.toUpperCase() === "\u001b"; +s.toLowerCase() === "\u001B"; +s.toUpperCase() === "\u000D"; +s.toLowerCase() === "\u000D"; +s.toLowerCase() === "\u{a}aa"; +s.toLowerCase() === "\u{A}aa"; +s.toUpperCase() === "{}"; +s.toLowerCase() === "{}"; +``` diff --git a/crates/biome_js_analyze/tests/specs/correctness/noStringCaseMismatch/valid.jsonc b/crates/biome_js_analyze/tests/specs/correctness/noStringCaseMismatch/valid.jsonc deleted file mode 100644 index 62566a81eaa4..000000000000 --- a/crates/biome_js_analyze/tests/specs/correctness/noStringCaseMismatch/valid.jsonc +++ /dev/null @@ -1,8 +0,0 @@ -[ - "s.toUpperCase() === 'ABC';", - "s.toLowerCase() === 'abc';", - "s.toUpperCase() === '20';", - "s.toLowerCase() === '20';", - "s.toLowerCase() === `eFg${12}`;", - "s.toLowerCase() == `eFg${12}`;" -] diff --git a/crates/biome_js_analyze/tests/specs/correctness/noStringCaseMismatch/valid.jsonc.snap b/crates/biome_js_analyze/tests/specs/correctness/noStringCaseMismatch/valid.jsonc.snap deleted file mode 100644 index d10c728db9e3..000000000000 --- a/crates/biome_js_analyze/tests/specs/correctness/noStringCaseMismatch/valid.jsonc.snap +++ /dev/null @@ -1,35 +0,0 @@ ---- -source: crates/biome_js_analyze/tests/spec_tests.rs -expression: valid.jsonc ---- -# Input -```cjs -s.toUpperCase() === 'ABC'; -``` - -# Input -```cjs -s.toLowerCase() === 'abc'; -``` - -# Input -```cjs -s.toUpperCase() === '20'; -``` - -# Input -```cjs -s.toLowerCase() === '20'; -``` - -# Input -```cjs -s.toLowerCase() === `eFg${12}`; -``` - -# Input -```cjs -s.toLowerCase() == `eFg${12}`; -``` - -