feat(linter/eslint): Implement unicode-bom rule (#3239)

Rule Detail:
[link](https://eslint.org/docs/latest/rules/unicode-bom)
This commit is contained in:
Jelle van der Waa 2024-05-12 13:39:02 +02:00 committed by GitHub
parent d45b28a3b9
commit 8244d2be0a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 143 additions and 0 deletions

View file

@ -115,6 +115,7 @@ mod eslint {
pub mod no_with;
pub mod radix;
pub mod require_yield;
pub mod unicode_bom;
pub mod use_isnan;
pub mod valid_typeof;
}
@ -471,6 +472,7 @@ oxc_macros::declare_all_lint_rules! {
eslint::no_with,
eslint::radix,
eslint::require_yield,
eslint::unicode_bom,
eslint::use_isnan,
eslint::valid_typeof,
eslint::no_await_in_loop,

View file

@ -0,0 +1,109 @@
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;
use crate::{context::LintContext, rule::Rule};
fn unexpected_unicode_bom_diagnostic(span0: Span) -> OxcDiagnostic {
OxcDiagnostic::warning("eslint(unicode-bom): Unexpected Unicode BOM (Byte Order Mark)")
.with_help("File must not begin with the Unicode BOM")
.with_labels([span0.into()])
}
fn expected_unicode_bom_diagnostic(span0: Span) -> OxcDiagnostic {
OxcDiagnostic::warning("eslint(unicode-bom): Expected Unicode BOM (Byte Order Mark)")
.with_help("File must begin with the Unicode BOM")
.with_labels([span0.into()])
}
#[derive(Debug, Default, Clone)]
pub struct UnicodeBom {
bom_option: BomOptionType,
}
declare_oxc_lint!(
/// ### What it does
///
/// Require or disallow Unicode byte order mark (BOM)
///
/// ### Why is this bad?
///
/// The Unicode Byte Order Mark (BOM) is used to specify whether code units are big endian or
/// little endian. That is, whether the most significant or least significant bytes come first.
/// UTF-8 does not require a BOM because byte ordering does not matter when characters are a
/// single byte. Since UTF-8 is the dominant encoding of the web, we make "never" the default
/// option.
///
/// ### Example
/// ```javascript
/// var a = 123;"
/// ```
UnicodeBom,
restriction,
);
impl Rule for UnicodeBom {
fn from_configuration(value: serde_json::Value) -> Self {
let obj = value.get(0);
Self {
bom_option: obj
.and_then(serde_json::Value::as_str)
.map(BomOptionType::from)
.unwrap_or_default(),
}
}
fn run_once(&self, ctx: &LintContext) {
let source = ctx.source_text();
let has_bomb = source.starts_with('');
if has_bomb && matches!(self.bom_option, BomOptionType::Never) {
ctx.diagnostic(unexpected_unicode_bom_diagnostic(Span::new(0, 0)));
}
if !has_bomb && matches!(self.bom_option, BomOptionType::Always) {
ctx.diagnostic(expected_unicode_bom_diagnostic(Span::new(0, 0)));
}
}
}
#[derive(Debug, Default, Clone)]
enum BomOptionType {
Always,
#[default]
Never,
}
impl BomOptionType {
pub fn from(raw: &str) -> Self {
match raw {
"always" => Self::Always,
_ => Self::Never,
}
}
}
#[test]
fn test() {
use crate::tester::Tester;
let pass = vec![
(" var a = 123;", Some(serde_json::json!(["always"]))),
("var a = 123;", Some(serde_json::json!(["never"]))),
("var a = 123; ", Some(serde_json::json!(["never"]))),
];
let fail = vec![
("var a = 123;", Some(serde_json::json!(["always"]))),
(
" // here's a comment
var a = 123;",
Some(serde_json::json!(["always"])),
),
(" var a = 123;", None),
(" var a = 123;", Some(serde_json::json!(["never"]))),
];
Tester::new(UnicodeBom::NAME, pass, fail).test_and_snapshot();
}

View file

@ -0,0 +1,32 @@
---
source: crates/oxc_linter/src/tester.rs
expression: unicode_bom
---
⚠ eslint(unicode-bom): Expected Unicode BOM (Byte Order Mark)
╭─[unicode_bom.tsx:1:1]
1 │ var a = 123;
· ▲
╰────
help: File must begin with the Unicode BOM
⚠ eslint(unicode-bom): Expected Unicode BOM (Byte Order Mark)
╭─[unicode_bom.tsx:1:1]
1 │ // here's a comment
· ▲
2 │ var a = 123;
╰────
help: File must begin with the Unicode BOM
⚠ eslint(unicode-bom): Unexpected Unicode BOM (Byte Order Mark)
╭─[unicode_bom.tsx:1:1]
1 │  var a = 123;
· ▲
╰────
help: File must not begin with the Unicode BOM
⚠ eslint(unicode-bom): Unexpected Unicode BOM (Byte Order Mark)
╭─[unicode_bom.tsx:1:1]
1 │  var a = 123;
· ▲
╰────
help: File must not begin with the Unicode BOM