mirror of
https://github.com/oxc-project/oxc.git
synced 2026-11-04 10:29:58 +00:00
fix(linter/eslint/no-misleading-character-class): detect more combining characters (#28733)
fixes https://github.com/oxc-project/oxc/issues/28729 Generated by Claude Sonnet 5.5 🤖 The upstream rules uses regex to detect if it is a combining character with the `\p` shorthand: https://github.com/eslint/eslint/blob/main/lib/rules/utils/unicode/is-combining-character.js#L11 Because there is no similar utility in rust, we currently have a self-managed list of character detection. This list now get extended to detect more characters for other languages like Arabic, Hebrew, Thai ... Verified manually that the failing test cases also fails upstream. Did not verfify if the list is really valid and covers all possible combining characters. I hope that the AI did no mistakes and included characters which are still valid.
This commit is contained in:
1 parent
74d50c1f32
commit
b5b3f3fc88
2 files changed
+310
-3
No files matched your search
@@ -265,9 +265,15 @@ fn regional_indicator_symbol_sequences(chars: &[&Character], ctx: &LintContext<'
|
||||
// - Combining Diacritical Marks for Symbols: U+20D0–U+20FF
|
||||
// - Combining Half Marks: U+FE20–U+FE2F
|
||||
//
|
||||
// Additional combining characters exist within script-specific blocks
|
||||
// (e.g., Devanagari signs, Hiragana/Katakana marks) and are not confined to a block,
|
||||
// but share the Mn/Mc/Me categories
|
||||
// Additional combining characters exist within script-specific blocks and are not
|
||||
// confined to a dedicated block, but share the Mn/Mc/Me categories. These are listed
|
||||
// per script in the `matches!` below, e.g.:
|
||||
// - Hebrew, Arabic, Syriac, Thaana
|
||||
// - Devanagari, Bengali, Gurmukhi, Gujarati, Oriya, Tamil, Telugu, Kannada, Malayalam, Sinhala
|
||||
// - Thai, Lao, Tibetan, Myanmar, Khmer, Mongolian
|
||||
// - Balinese, Javanese, Cham, Meetei Mayek, Hiragana/Katakana marks, and others
|
||||
//
|
||||
// Supplementary-plane scripts are only partially covered (Brahmi, Kharoshthi, Grantha).
|
||||
//
|
||||
// B. Variation Selectors (also Combining)
|
||||
//
|
||||
@@ -283,6 +289,50 @@ fn is_combining_character(value: u32) -> bool {
|
||||
0x1DC0..=0x1DFF | // Combining Diacritical Marks Supplement
|
||||
0x20D0..=0x20FF | // Combining Diacritical Marks for Symbols
|
||||
0xFE20..=0xFE2F | // Combining Half Marks
|
||||
0x0483..=0x0489 | // Cyrillic
|
||||
0x0591..=0x05BD | 0x05BF | 0x05C1..=0x05C2 | 0x05C4..=0x05C5 | 0x05C7 | // Hebrew
|
||||
0x0610..=0x061A | 0x064B..=0x065F | 0x0670 | 0x06D6..=0x06DC | 0x06DF..=0x06E4 | 0x06E7..=0x06E8 | 0x06EA..=0x06ED | // Arabic
|
||||
0x0711 | 0x0730..=0x074A | // Syriac
|
||||
0x07A6..=0x07B0 | // Thaana
|
||||
0x07EB..=0x07F3 | 0x07FD | // NKo
|
||||
0x0816..=0x0819 | 0x081B..=0x0823 | 0x0825..=0x0827 | 0x0829..=0x082D | // Samaritan
|
||||
0x0859..=0x085B | // Mandaic
|
||||
0x0898..=0x089F | 0x08CA..=0x08E1 | // Arabic Extended
|
||||
0x08E3..=0x0903 | 0x093A..=0x093C | 0x093E..=0x094F | 0x0951..=0x0957 | 0x0962..=0x0963 | // Devanagari
|
||||
0x0981..=0x0983 | 0x09BC | 0x09BE..=0x09C4 | 0x09C7..=0x09C8 | 0x09CB..=0x09CD | 0x09D7 | 0x09E2..=0x09E3 | 0x09FE | // Bengali
|
||||
0x0A01..=0x0A03 | 0x0A3C | 0x0A3E..=0x0A42 | 0x0A47..=0x0A48 | 0x0A4B..=0x0A4D | 0x0A51 | 0x0A70..=0x0A71 | 0x0A75 | // Gurmukhi
|
||||
0x0A81..=0x0A83 | 0x0ABC | 0x0ABE..=0x0AC5 | 0x0AC7..=0x0AC9 | 0x0ACB..=0x0ACD | 0x0AE2..=0x0AE3 | 0x0AFA..=0x0AFF | // Gujarati
|
||||
0x0B01..=0x0B03 | 0x0B3C | 0x0B3E..=0x0B44 | 0x0B47..=0x0B48 | 0x0B4B..=0x0B4D | 0x0B55..=0x0B57 | 0x0B62..=0x0B63 | // Oriya
|
||||
0x0B82 | 0x0BBE..=0x0BC2 | 0x0BC6..=0x0BC8 | 0x0BCA..=0x0BCD | 0x0BD7 | // Tamil
|
||||
0x0C00..=0x0C04 | 0x0C3C | 0x0C3E..=0x0C44 | 0x0C46..=0x0C48 | 0x0C4A..=0x0C4D | 0x0C55..=0x0C56 | 0x0C62..=0x0C63 | // Telugu
|
||||
0x0C81..=0x0C83 | 0x0CBC | 0x0CBE..=0x0CC4 | 0x0CC6..=0x0CC8 | 0x0CCA..=0x0CCD | 0x0CD5..=0x0CD6 | 0x0CE2..=0x0CE3 | 0x0CF3 | // Kannada
|
||||
0x0D00..=0x0D03 | 0x0D3B..=0x0D3C | 0x0D3E..=0x0D44 | 0x0D46..=0x0D48 | 0x0D4A..=0x0D4D | 0x0D57 | 0x0D62..=0x0D63 | // Malayalam
|
||||
0x0D81..=0x0D83 | 0x0DCA | 0x0DCF..=0x0DD4 | 0x0DD6 | 0x0DD8..=0x0DDF | 0x0DF2..=0x0DF3 | // Sinhala
|
||||
0x0E31 | 0x0E34..=0x0E3A | 0x0E47..=0x0E4E | // Thai
|
||||
0x0EB1 | 0x0EB4..=0x0EBC | 0x0EC8..=0x0ECE | // Lao
|
||||
0x0F18..=0x0F19 | 0x0F35 | 0x0F37 | 0x0F39 | 0x0F3E..=0x0F3F | 0x0F71..=0x0F84 | 0x0F86..=0x0F87 | 0x0F8D..=0x0FBC | 0x0FC6 | // Tibetan
|
||||
0x102B..=0x103E | 0x1056..=0x1059 | 0x105E..=0x1060 | 0x1062..=0x1064 | 0x1067..=0x106D | 0x1071..=0x1074 | 0x1082..=0x108D | 0x108F | 0x109A..=0x109D | // Myanmar
|
||||
0x135D..=0x135F | // Ethiopic
|
||||
0x1712..=0x1715 | 0x1732..=0x1734 | 0x1752..=0x1753 | 0x1772..=0x1773 | // Tagalog, Hanunoo, Buhid, Tagbanwa
|
||||
0x17B4..=0x17D3 | 0x17DD | // Khmer
|
||||
0x180B..=0x180D | 0x180F | 0x1885..=0x1886 | 0x18A9 | // Mongolian
|
||||
0x1920..=0x192B | 0x1930..=0x193B | // Limbu
|
||||
// spellchecker:disable-next-line
|
||||
0x1A17..=0x1A1B | 0x1A55..=0x1A7F | // Buginese, Tai Tham
|
||||
0x1B00..=0x1B04 | 0x1B34..=0x1B44 | 0x1B6B..=0x1B73 | // Balinese
|
||||
0x1B80..=0x1B82 | 0x1BA1..=0x1BAD | 0x1BE6..=0x1BF3 | // Sundanese, Batak
|
||||
0x1C24..=0x1C37 | // Lepcha
|
||||
0x1CD0..=0x1CD2 | 0x1CD4..=0x1CE8 | 0x1CED | 0x1CF4 | 0x1CF7..=0x1CF9 | // Vedic Extensions
|
||||
0x302A..=0x302F | 0x3099..=0x309A | // CJK / Kana combining marks
|
||||
0xA66F..=0xA672 | 0xA674..=0xA67D | 0xA69E..=0xA69F | 0xA6F0..=0xA6F1 | // Cyrillic Extended-B, Bamum
|
||||
0xA802 | 0xA806 | 0xA80B | 0xA823..=0xA827 | // Syloti Nagri
|
||||
0xA880..=0xA881 | 0xA8B4..=0xA8C5 | 0xA8E0..=0xA8F1 | // Saurashtra, Devanagari Extended
|
||||
0xA926..=0xA92D | 0xA947..=0xA953 | 0xA980..=0xA983 | 0xA9B3..=0xA9C0 | // Kayah Li, Rejang, Javanese
|
||||
0xAA29..=0xAA36 | 0xAAEB..=0xAAEF | 0xABE3..=0xABEA | 0xABEC..=0xABED | // Cham, Meetei Mayek
|
||||
0xFB1E | // Hebrew point judeo-spanish varika
|
||||
0x10A01..=0x10A0F | 0x10A38..=0x10A3F | // Kharoshthi
|
||||
0x11000..=0x11002 | 0x11038..=0x11046 | 0x11070 | 0x11073..=0x11074 | 0x1107F..=0x11082 | // Brahmi
|
||||
0x11300..=0x11303 | 0x1133B..=0x1133C | 0x1133E..=0x11344 | 0x11347..=0x11348 | 0x1134B..=0x1134D | 0x11357 | 0x11362..=0x11363 | 0x11366..=0x1136C | 0x11370..=0x11374 | // Grantha
|
||||
0xFE00..=0xFE0F | // Variation Selectors (Basic)
|
||||
0xE0100..=0xE01EF // Variation Selectors (Supplement)
|
||||
)
|
||||
@@ -824,6 +874,39 @@ fn test() {
|
||||
// https://github.com/oxc-project/oxc/issues/19090 -- without u flag it should fail
|
||||
// this should not be a `UnicodePropertyEscape`
|
||||
(r"/[\u200c\u200d\p{ID_Continue}.]/", None),
|
||||
// https://github.com/oxc-project/oxc/issues/28729
|
||||
("/[ગુ]/", None),
|
||||
("/[कि]/", None),
|
||||
("/[ક્]/", None),
|
||||
("/[नमस्ते]/", None),
|
||||
("new RegExp('[ગુ]', 'u');", None),
|
||||
// combining marks of other scripts (base letter + mark)
|
||||
("/[а҃]/u", None), // Cyrillic
|
||||
("/[אָ]/u", None), // Hebrew
|
||||
("/[بَ]/u", None), // Arabic
|
||||
("/[ܐܰ]/u", None), // Syriac
|
||||
("/[ހަ]/u", None), // Thaana
|
||||
("/[ߊ߫]/u", None), // NKo
|
||||
("/[কা]/u", None), // Bengali
|
||||
("/[ਕਾ]/u", None), // Gurmukhi
|
||||
("/[କା]/u", None), // Oriya
|
||||
("/[கா]/u", None), // Tamil
|
||||
("/[కా]/u", None), // Telugu
|
||||
("/[ಕಾ]/u", None), // Kannada
|
||||
("/[കാ]/u", None), // Malayalam
|
||||
("/[කා]/u", None), // Sinhala
|
||||
("/[กั]/u", None), // Thai
|
||||
("/[ກັ]/u", None), // Lao
|
||||
("/[ཀཱ]/u", None), // Tibetan
|
||||
("/[ကါ]/u", None), // Myanmar
|
||||
("/[កា]/u", None), // Khmer
|
||||
("/[ᠠ᠋]/u", None), // Mongolian
|
||||
("/[ᬆ]/u", None), // Balinese
|
||||
("/[が]/u", None), // Kana
|
||||
("/[ꦏꦴ]/u", None), // Javanese
|
||||
("/[𑀓𑀸]/u", None), // Brahmi
|
||||
("/[𐨕𐨁]/u", None), // Kharoshthi
|
||||
("/[𑌕𑌾]/u", None), // Grantha
|
||||
];
|
||||
|
||||
let fix = vec![
|
||||
|
||||
@@ -1222,3 +1222,227 @@ source: crates/oxc_linter/src/tester.rs
|
||||
· ──────────────
|
||||
╰────
|
||||
help: Use Unicode code point escapes (e.g., \u{1F468}\u200D\u{1F469} for '👨👩') instead of zero-width joiner sequences in character classes.
|
||||
|
||||
⚠ eslint(no-misleading-character-class): Unexpected combining class in character class.
|
||||
╭─[no_misleading_character_class.tsx:1:3]
|
||||
1 │ /[ગુ]/
|
||||
· ─
|
||||
╰────
|
||||
help: Replace the character with its normalized form (NFC) or use Unicode code point escapes instead of combining sequences.
|
||||
|
||||
⚠ eslint(no-misleading-character-class): Unexpected combining class in character class.
|
||||
╭─[no_misleading_character_class.tsx:1:3]
|
||||
1 │ /[कि]/
|
||||
· ──
|
||||
╰────
|
||||
help: Replace the character with its normalized form (NFC) or use Unicode code point escapes instead of combining sequences.
|
||||
|
||||
⚠ eslint(no-misleading-character-class): Unexpected combining class in character class.
|
||||
╭─[no_misleading_character_class.tsx:1:3]
|
||||
1 │ /[ક્]/
|
||||
· ─
|
||||
╰────
|
||||
help: Replace the character with its normalized form (NFC) or use Unicode code point escapes instead of combining sequences.
|
||||
|
||||
⚠ eslint(no-misleading-character-class): Unexpected combining class in character class.
|
||||
╭─[no_misleading_character_class.tsx:1:9]
|
||||
1 │ /[नमस्ते]/
|
||||
· ─
|
||||
╰────
|
||||
help: Replace the character with its normalized form (NFC) or use Unicode code point escapes instead of combining sequences.
|
||||
|
||||
⚠ eslint(no-misleading-character-class): Unexpected combining class in character class.
|
||||
╭─[no_misleading_character_class.tsx:1:15]
|
||||
1 │ /[नमस्ते]/
|
||||
· ─
|
||||
╰────
|
||||
help: Replace the character with its normalized form (NFC) or use Unicode code point escapes instead of combining sequences.
|
||||
|
||||
⚠ eslint(no-misleading-character-class): Unexpected combining class in character class.
|
||||
╭─[no_misleading_character_class.tsx:1:14]
|
||||
1 │ new RegExp('[ગુ]', 'u');
|
||||
· ─
|
||||
╰────
|
||||
help: Replace the character with its normalized form (NFC) or use Unicode code point escapes instead of combining sequences.
|
||||
|
||||
⚠ eslint(no-misleading-character-class): Unexpected combining class in character class.
|
||||
╭─[no_misleading_character_class.tsx:1:3]
|
||||
1 │ /[а҃]/u
|
||||
· ─
|
||||
╰────
|
||||
help: Replace the character with its normalized form (NFC) or use Unicode code point escapes instead of combining sequences.
|
||||
|
||||
⚠ eslint(no-misleading-character-class): Unexpected combining class in character class.
|
||||
╭─[no_misleading_character_class.tsx:1:3]
|
||||
1 │ /[אָ]/u
|
||||
· ─
|
||||
╰────
|
||||
help: Replace the character with its normalized form (NFC) or use Unicode code point escapes instead of combining sequences.
|
||||
|
||||
⚠ eslint(no-misleading-character-class): Unexpected combining class in character class.
|
||||
╭─[no_misleading_character_class.tsx:1:3]
|
||||
1 │ /[بَ]/u
|
||||
· ─
|
||||
╰────
|
||||
help: Replace the character with its normalized form (NFC) or use Unicode code point escapes instead of combining sequences.
|
||||
|
||||
⚠ eslint(no-misleading-character-class): Unexpected combining class in character class.
|
||||
╭─[no_misleading_character_class.tsx:1:3]
|
||||
1 │ /[ܐܰ]/u
|
||||
· ─
|
||||
╰────
|
||||
help: Replace the character with its normalized form (NFC) or use Unicode code point escapes instead of combining sequences.
|
||||
|
||||
⚠ eslint(no-misleading-character-class): Unexpected combining class in character class.
|
||||
╭─[no_misleading_character_class.tsx:1:3]
|
||||
1 │ /[ހަ]/u
|
||||
· ─
|
||||
╰────
|
||||
help: Replace the character with its normalized form (NFC) or use Unicode code point escapes instead of combining sequences.
|
||||
|
||||
⚠ eslint(no-misleading-character-class): Unexpected combining class in character class.
|
||||
╭─[no_misleading_character_class.tsx:1:3]
|
||||
1 │ /[ߊ߫]/u
|
||||
· ─
|
||||
╰────
|
||||
help: Replace the character with its normalized form (NFC) or use Unicode code point escapes instead of combining sequences.
|
||||
|
||||
⚠ eslint(no-misleading-character-class): Unexpected combining class in character class.
|
||||
╭─[no_misleading_character_class.tsx:1:3]
|
||||
1 │ /[কা]/u
|
||||
· ─
|
||||
╰────
|
||||
help: Replace the character with its normalized form (NFC) or use Unicode code point escapes instead of combining sequences.
|
||||
|
||||
⚠ eslint(no-misleading-character-class): Unexpected combining class in character class.
|
||||
╭─[no_misleading_character_class.tsx:1:3]
|
||||
1 │ /[ਕਾ]/u
|
||||
· ──
|
||||
╰────
|
||||
help: Replace the character with its normalized form (NFC) or use Unicode code point escapes instead of combining sequences.
|
||||
|
||||
⚠ eslint(no-misleading-character-class): Unexpected combining class in character class.
|
||||
╭─[no_misleading_character_class.tsx:1:3]
|
||||
1 │ /[କା]/u
|
||||
· ─
|
||||
╰────
|
||||
help: Replace the character with its normalized form (NFC) or use Unicode code point escapes instead of combining sequences.
|
||||
|
||||
⚠ eslint(no-misleading-character-class): Unexpected combining class in character class.
|
||||
╭─[no_misleading_character_class.tsx:1:3]
|
||||
1 │ /[கா]/u
|
||||
· ─
|
||||
╰────
|
||||
help: Replace the character with its normalized form (NFC) or use Unicode code point escapes instead of combining sequences.
|
||||
|
||||
⚠ eslint(no-misleading-character-class): Unexpected combining class in character class.
|
||||
╭─[no_misleading_character_class.tsx:1:3]
|
||||
1 │ /[కా]/u
|
||||
· ─
|
||||
╰────
|
||||
help: Replace the character with its normalized form (NFC) or use Unicode code point escapes instead of combining sequences.
|
||||
|
||||
⚠ eslint(no-misleading-character-class): Unexpected combining class in character class.
|
||||
╭─[no_misleading_character_class.tsx:1:3]
|
||||
1 │ /[ಕಾ]/u
|
||||
· ──
|
||||
╰────
|
||||
help: Replace the character with its normalized form (NFC) or use Unicode code point escapes instead of combining sequences.
|
||||
|
||||
⚠ eslint(no-misleading-character-class): Unexpected combining class in character class.
|
||||
╭─[no_misleading_character_class.tsx:1:3]
|
||||
1 │ /[കാ]/u
|
||||
· ─
|
||||
╰────
|
||||
help: Replace the character with its normalized form (NFC) or use Unicode code point escapes instead of combining sequences.
|
||||
|
||||
⚠ eslint(no-misleading-character-class): Unexpected combining class in character class.
|
||||
╭─[no_misleading_character_class.tsx:1:3]
|
||||
1 │ /[කා]/u
|
||||
· ─
|
||||
╰────
|
||||
help: Replace the character with its normalized form (NFC) or use Unicode code point escapes instead of combining sequences.
|
||||
|
||||
⚠ eslint(no-misleading-character-class): Unexpected combining class in character class.
|
||||
╭─[no_misleading_character_class.tsx:1:3]
|
||||
1 │ /[กั]/u
|
||||
· ─
|
||||
╰────
|
||||
help: Replace the character with its normalized form (NFC) or use Unicode code point escapes instead of combining sequences.
|
||||
|
||||
⚠ eslint(no-misleading-character-class): Unexpected combining class in character class.
|
||||
╭─[no_misleading_character_class.tsx:1:3]
|
||||
1 │ /[ກັ]/u
|
||||
· ─
|
||||
╰────
|
||||
help: Replace the character with its normalized form (NFC) or use Unicode code point escapes instead of combining sequences.
|
||||
|
||||
⚠ eslint(no-misleading-character-class): Unexpected combining class in character class.
|
||||
╭─[no_misleading_character_class.tsx:1:3]
|
||||
1 │ /[ཀཱ]/u
|
||||
· ─
|
||||
╰────
|
||||
help: Replace the character with its normalized form (NFC) or use Unicode code point escapes instead of combining sequences.
|
||||
|
||||
⚠ eslint(no-misleading-character-class): Unexpected combining class in character class.
|
||||
╭─[no_misleading_character_class.tsx:1:3]
|
||||
1 │ /[ကါ]/u
|
||||
· ──
|
||||
╰────
|
||||
help: Replace the character with its normalized form (NFC) or use Unicode code point escapes instead of combining sequences.
|
||||
|
||||
⚠ eslint(no-misleading-character-class): Unexpected combining class in character class.
|
||||
╭─[no_misleading_character_class.tsx:1:3]
|
||||
1 │ /[កា]/u
|
||||
· ──
|
||||
╰────
|
||||
help: Replace the character with its normalized form (NFC) or use Unicode code point escapes instead of combining sequences.
|
||||
|
||||
⚠ eslint(no-misleading-character-class): Unexpected combining class in character class.
|
||||
╭─[no_misleading_character_class.tsx:1:3]
|
||||
1 │ /[ᠠ᠋]/u
|
||||
· ─
|
||||
╰────
|
||||
help: Replace the character with its normalized form (NFC) or use Unicode code point escapes instead of combining sequences.
|
||||
|
||||
⚠ eslint(no-misleading-character-class): Unexpected combining class in character class.
|
||||
╭─[no_misleading_character_class.tsx:1:3]
|
||||
1 │ /[ᬆ]/u
|
||||
· ─
|
||||
╰────
|
||||
help: Replace the character with its normalized form (NFC) or use Unicode code point escapes instead of combining sequences.
|
||||
|
||||
⚠ eslint(no-misleading-character-class): Unexpected combining class in character class.
|
||||
╭─[no_misleading_character_class.tsx:1:3]
|
||||
1 │ /[が]/u
|
||||
· ──
|
||||
╰────
|
||||
help: Replace the character with its normalized form (NFC) or use Unicode code point escapes instead of combining sequences.
|
||||
|
||||
⚠ eslint(no-misleading-character-class): Unexpected combining class in character class.
|
||||
╭─[no_misleading_character_class.tsx:1:3]
|
||||
1 │ /[ꦏꦴ]/u
|
||||
· ──
|
||||
╰────
|
||||
help: Replace the character with its normalized form (NFC) or use Unicode code point escapes instead of combining sequences.
|
||||
|
||||
⚠ eslint(no-misleading-character-class): Unexpected combining class in character class.
|
||||
╭─[no_misleading_character_class.tsx:1:3]
|
||||
1 │ /[𑀓𑀸]/u
|
||||
· ─
|
||||
╰────
|
||||
help: Replace the character with its normalized form (NFC) or use Unicode code point escapes instead of combining sequences.
|
||||
|
||||
⚠ eslint(no-misleading-character-class): Unexpected combining class in character class.
|
||||
╭─[no_misleading_character_class.tsx:1:3]
|
||||
1 │ /[𐨕𐨁]/u
|
||||
· ─
|
||||
╰────
|
||||
help: Replace the character with its normalized form (NFC) or use Unicode code point escapes instead of combining sequences.
|
||||
|
||||
⚠ eslint(no-misleading-character-class): Unexpected combining class in character class.
|
||||
╭─[no_misleading_character_class.tsx:1:3]
|
||||
1 │ /[𑌕𑌾]/u
|
||||
· ─
|
||||
╰────
|
||||
help: Replace the character with its normalized form (NFC) or use Unicode code point escapes instead of combining sequences.
|
||||
Reference in new issue
Block a user