Skip to content

Commit

Permalink
feat(linter) eslint-plugin-unicorn: prefer blob reading methods (#1168)
Browse files Browse the repository at this point in the history
  • Loading branch information
camc314 committed Nov 6, 2023
1 parent 5cf8543 commit 9b66646
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 0 deletions.
2 changes: 2 additions & 0 deletions crates/oxc_linter/src/rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ mod unicorn {
pub mod no_thenable;
pub mod no_unnecessary_await;
pub mod prefer_array_flat_map;
pub mod prefer_blob_reading_methods;
pub mod prefer_code_point;
pub mod prefer_date_now;
pub mod prefer_logical_operator_over_ternary;
Expand Down Expand Up @@ -284,6 +285,7 @@ oxc_macros::declare_all_lint_rules! {
unicorn::no_thenable,
unicorn::no_unnecessary_await,
unicorn::prefer_array_flat_map,
unicorn::prefer_blob_reading_methods,
unicorn::prefer_code_point,
unicorn::prefer_date_now,
unicorn::prefer_logical_operator_over_ternary,
Expand Down
90 changes: 90 additions & 0 deletions crates/oxc_linter/src/rules/unicorn/prefer_blob_reading_methods.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
use oxc_ast::{ast::Expression, AstKind};
use oxc_diagnostics::{
miette::{self, Diagnostic},
thiserror::{self, Error},
};
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;

use crate::{context::LintContext, rule::Rule, AstNode};

#[derive(Debug, Error, Diagnostic)]
#[error("eslint-plugin-unicorn(prefer-blob-reading-methods): Prefer `Blob#{1}()` over `FileReader#{2}(blob)`.")]
#[diagnostic(severity(warning))]
struct PreferBlobReadingMethodsDiagnostic(#[label] pub Span, pub &'static str, pub &'static str);

#[derive(Debug, Default, Clone)]
pub struct PreferBlobReadingMethods;

declare_oxc_lint!(
/// ### What it does
///
/// Recommends using `Blob#text()` and `Blob#arrayBuffer()` over `FileReader#readAsText()` and `FileReader#readAsArrayBuffer()`.
///
/// ### Why is this bad?
///
/// `FileReader` predates promises, and the newer [`Blob#arrayBuffer()`](https://developer.mozilla.org/en-US/docs/Web/API/Blob/arrayBuffer) and [`Blob#text()`](https://developer.mozilla.org/en-US/docs/Web/API/Blob/text) methods are much cleaner and easier to use.
///
/// ### Example
/// ```javascript
/// // bad
/// const arrayBuffer = await new Promise((resolve, reject) => {
/// const fileReader = new FileReader();
/// fileReader.addEventListener('load', () => {
/// resolve(fileReader.result);
/// });
/// fileReader.addEventListener('error', () => {
/// reject(fileReader.error);
/// });
/// fileReader.readAsArrayBuffer(blob);
/// });
///
/// // good
/// const arrayBuffer = await blob.arrayBuffer();
/// ```
PreferBlobReadingMethods,
pedantic
);

impl Rule for PreferBlobReadingMethods {
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
let AstKind::CallExpression(call_expr) = node.kind() else { return };

let Expression::MemberExpression(member_expr) = &call_expr.callee else { return };

if member_expr.is_computed()
|| member_expr.optional()
|| call_expr.optional
|| call_expr.arguments.len() != 1
{
return;
}

let (current, replacement, span) = match member_expr.static_property_info() {
Some((span, "readAsText")) => ("readAsText", "text", span),
Some((span, "readAsArrayBuffer")) => ("readAsArrayBuffer", "arrayBuffer", span),
_ => return,
};

ctx.diagnostic(PreferBlobReadingMethodsDiagnostic(span, replacement, current));
}
}

#[test]
fn test() {
use crate::tester::Tester;

let pass = vec![
r#"blob.arrayBuffer()"#,
r#"blob.text()"#,
r#"new Response(blob).arrayBuffer()"#,
r#"new Response(blob).text()"#,
r#"fileReader.readAsDataURL(blob)"#,
r#"fileReader.readAsBinaryString(blob)"#,
r#"fileReader.readAsText(blob, "ascii")"#,
];

let fail = vec![r#"fileReader.readAsArrayBuffer(blob)"#, r#"fileReader.readAsText(blob)"#];

Tester::new_without_config(PreferBlobReadingMethods::NAME, pass, fail).test_and_snapshot();
}
17 changes: 17 additions & 0 deletions crates/oxc_linter/src/snapshots/prefer_blob_reading_methods.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
source: crates/oxc_linter/src/tester.rs
expression: prefer_blob_reading_methods
---
eslint-plugin-unicorn(prefer-blob-reading-methods): Prefer `Blob#arrayBuffer()` over `FileReader#readAsArrayBuffer(blob)`.
╭─[prefer_blob_reading_methods.tsx:1:1]
1fileReader.readAsArrayBuffer(blob)
· ─────────────────
╰────

eslint-plugin-unicorn(prefer-blob-reading-methods): Prefer `Blob#text()` over `FileReader#readAsText(blob)`.
╭─[prefer_blob_reading_methods.tsx:1:1]
1fileReader.readAsText(blob)
· ──────────
╰────


0 comments on commit 9b66646

Please sign in to comment.