feat(linter): eslint-plugin-unicorn no-await-expression-member (style) (#1569)

This commit is contained in:
Ken-HH24 2023-11-29 11:26:29 +08:00 committed by GitHub
parent f7cb7838e5
commit 3b2b6a013a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 286 additions and 0 deletions

View file

@ -154,6 +154,7 @@ mod unicorn {
pub mod filename_case;
pub mod new_for_builtins;
pub mod no_abusive_eslint_disable;
pub mod no_await_expression_member;
pub mod no_console_spaces;
pub mod no_document_cookie;
pub mod no_empty_file;
@ -330,6 +331,7 @@ oxc_macros::declare_all_lint_rules! {
unicorn::filename_case,
unicorn::new_for_builtins,
unicorn::no_abusive_eslint_disable,
unicorn::no_await_expression_member,
unicorn::no_console_spaces,
unicorn::no_document_cookie,
unicorn::no_empty_file,

View file

@ -0,0 +1,104 @@
use oxc_ast::{ast::Expression, AstKind};
use oxc_diagnostics::{
miette::{self, Diagnostic},
thiserror::Error,
};
use oxc_macros::declare_oxc_lint;
use oxc_span::{GetSpan, Span};
use crate::{context::LintContext, rule::Rule, AstNode};
#[derive(Debug, Error, Diagnostic)]
#[error("eslint-plugin-unicorn(no-await-expression-member): Disallow member access from await expression")]
#[diagnostic(severity(warning), help("When accessing a member from an await expression, the await expression has to be parenthesized, which is not readable."))]
struct NoAwaitExpressionMemberDiagnostic(#[label] pub Span);
#[derive(Debug, Default, Clone)]
pub struct NoAwaitExpressionMember;
declare_oxc_lint!(
/// ### What it does
///
/// This rule disallows member access from await expression
///
/// ### Why is this bad?
///
/// When accessing a member from an await expression,
/// the await expression has to be parenthesized, which is not readable.
///
/// ### Example
/// ```javascript
/// // Bad
/// const secondElement = (await getArray())[1];
///
/// // Good
/// const [, secondElement] = await getArray();
/// ```
NoAwaitExpressionMember,
style
);
impl Rule for NoAwaitExpressionMember {
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
let AstKind::MemberExpression(member_expr) = node.kind() else { return };
let Expression::ParenthesizedExpression(paren_expr) = member_expr.object() else {
return;
};
if matches!(paren_expr.expression, Expression::AwaitExpression(_)) {
let node_span = member_expr.span();
ctx.diagnostic(NoAwaitExpressionMemberDiagnostic(node_span));
}
}
}
#[test]
fn test() {
use crate::tester::Tester;
let pass = vec![
(r"const foo = await promise", None),
(r"const {foo: bar} = await promise", None),
(r"const foo = !await promise", None),
(r"const foo = typeof await promise", None),
(r"const foo = await notPromise.method()", None),
(r"const foo = foo[await promise]", None),
// These await expression need parenthesized, but rarely used
(r"new (await promiseReturnsAClass)", None),
(r"(await promiseReturnsAFunction)()", None),
// typescript
(r"async function foo () {return (await promise) as string;}", None),
];
let fail = vec![
(r"(await promise)[0]", None),
(r"(await promise).property", None),
(r"const foo = (await promise).bar()", None),
(r"const foo = (await promise).bar?.()", None),
(r"const foo = (await promise)?.bar()", None),
(r"const firstElement = (await getArray())[0]", None),
(r"const secondElement = (await getArray())[1]", None),
(r"const thirdElement = (await getArray())[2]", None),
(r"const optionalFirstElement = (await getArray())?.[0]", None),
(r"const {propertyOfFirstElement} = (await getArray())[0]", None),
(r"const [firstElementOfFirstElement] = (await getArray())[0]", None),
(r"let foo, firstElement = (await getArray())[0]", None),
(r"var firstElement = (await getArray())[0], bar", None),
(r"const property = (await getObject()).property", None),
(r"const renamed = (await getObject()).property", None),
(r"const property = (await getObject())[property]", None),
(r"const property = (await getObject())?.property", None),
(r"const {propertyOfProperty} = (await getObject()).property", None),
(r"const {propertyOfProperty} = (await getObject()).propertyOfProperty", None),
(r"const [firstElementOfProperty] = (await getObject()).property", None),
(r"const [firstElementOfProperty] = (await getObject()).firstElementOfProperty", None),
(r"firstElement = (await getArray())[0]", None),
(r"property = (await getArray()).property", None),
// typescript
(r"const foo: Type = (await promise)[0]", None),
(r"const foo: Type | A = (await promise).foo", None),
];
Tester::new(NoAwaitExpressionMember::NAME, pass, fail).test_and_snapshot();
}

View file

@ -0,0 +1,180 @@
---
source: crates/oxc_linter/src/tester.rs
expression: no_await_expression_member
---
⚠ eslint-plugin-unicorn(no-await-expression-member): Disallow member access from await expression
╭─[no_await_expression_member.tsx:1:1]
1 │ (await promise)[0]
· ──────────────────
╰────
help: When accessing a member from an await expression, the await expression has to be parenthesized, which is not readable.
⚠ eslint-plugin-unicorn(no-await-expression-member): Disallow member access from await expression
╭─[no_await_expression_member.tsx:1:1]
1 │ (await promise).property
· ────────────────────────
╰────
help: When accessing a member from an await expression, the await expression has to be parenthesized, which is not readable.
⚠ eslint-plugin-unicorn(no-await-expression-member): Disallow member access from await expression
╭─[no_await_expression_member.tsx:1:1]
1 │ const foo = (await promise).bar()
· ───────────────────
╰────
help: When accessing a member from an await expression, the await expression has to be parenthesized, which is not readable.
⚠ eslint-plugin-unicorn(no-await-expression-member): Disallow member access from await expression
╭─[no_await_expression_member.tsx:1:1]
1 │ const foo = (await promise).bar?.()
· ───────────────────
╰────
help: When accessing a member from an await expression, the await expression has to be parenthesized, which is not readable.
⚠ eslint-plugin-unicorn(no-await-expression-member): Disallow member access from await expression
╭─[no_await_expression_member.tsx:1:1]
1 │ const foo = (await promise)?.bar()
· ────────────────────
╰────
help: When accessing a member from an await expression, the await expression has to be parenthesized, which is not readable.
⚠ eslint-plugin-unicorn(no-await-expression-member): Disallow member access from await expression
╭─[no_await_expression_member.tsx:1:1]
1 │ const firstElement = (await getArray())[0]
· ─────────────────────
╰────
help: When accessing a member from an await expression, the await expression has to be parenthesized, which is not readable.
⚠ eslint-plugin-unicorn(no-await-expression-member): Disallow member access from await expression
╭─[no_await_expression_member.tsx:1:1]
1 │ const secondElement = (await getArray())[1]
· ─────────────────────
╰────
help: When accessing a member from an await expression, the await expression has to be parenthesized, which is not readable.
⚠ eslint-plugin-unicorn(no-await-expression-member): Disallow member access from await expression
╭─[no_await_expression_member.tsx:1:1]
1 │ const thirdElement = (await getArray())[2]
· ─────────────────────
╰────
help: When accessing a member from an await expression, the await expression has to be parenthesized, which is not readable.
⚠ eslint-plugin-unicorn(no-await-expression-member): Disallow member access from await expression
╭─[no_await_expression_member.tsx:1:1]
1 │ const optionalFirstElement = (await getArray())?.[0]
· ───────────────────────
╰────
help: When accessing a member from an await expression, the await expression has to be parenthesized, which is not readable.
⚠ eslint-plugin-unicorn(no-await-expression-member): Disallow member access from await expression
╭─[no_await_expression_member.tsx:1:1]
1 │ const {propertyOfFirstElement} = (await getArray())[0]
· ─────────────────────
╰────
help: When accessing a member from an await expression, the await expression has to be parenthesized, which is not readable.
⚠ eslint-plugin-unicorn(no-await-expression-member): Disallow member access from await expression
╭─[no_await_expression_member.tsx:1:1]
1 │ const [firstElementOfFirstElement] = (await getArray())[0]
· ─────────────────────
╰────
help: When accessing a member from an await expression, the await expression has to be parenthesized, which is not readable.
⚠ eslint-plugin-unicorn(no-await-expression-member): Disallow member access from await expression
╭─[no_await_expression_member.tsx:1:1]
1 │ let foo, firstElement = (await getArray())[0]
· ─────────────────────
╰────
help: When accessing a member from an await expression, the await expression has to be parenthesized, which is not readable.
⚠ eslint-plugin-unicorn(no-await-expression-member): Disallow member access from await expression
╭─[no_await_expression_member.tsx:1:1]
1 │ var firstElement = (await getArray())[0], bar
· ─────────────────────
╰────
help: When accessing a member from an await expression, the await expression has to be parenthesized, which is not readable.
⚠ eslint-plugin-unicorn(no-await-expression-member): Disallow member access from await expression
╭─[no_await_expression_member.tsx:1:1]
1 │ const property = (await getObject()).property
· ────────────────────────────
╰────
help: When accessing a member from an await expression, the await expression has to be parenthesized, which is not readable.
⚠ eslint-plugin-unicorn(no-await-expression-member): Disallow member access from await expression
╭─[no_await_expression_member.tsx:1:1]
1 │ const renamed = (await getObject()).property
· ────────────────────────────
╰────
help: When accessing a member from an await expression, the await expression has to be parenthesized, which is not readable.
⚠ eslint-plugin-unicorn(no-await-expression-member): Disallow member access from await expression
╭─[no_await_expression_member.tsx:1:1]
1 │ const property = (await getObject())[property]
· ─────────────────────────────
╰────
help: When accessing a member from an await expression, the await expression has to be parenthesized, which is not readable.
⚠ eslint-plugin-unicorn(no-await-expression-member): Disallow member access from await expression
╭─[no_await_expression_member.tsx:1:1]
1 │ const property = (await getObject())?.property
· ─────────────────────────────
╰────
help: When accessing a member from an await expression, the await expression has to be parenthesized, which is not readable.
⚠ eslint-plugin-unicorn(no-await-expression-member): Disallow member access from await expression
╭─[no_await_expression_member.tsx:1:1]
1 │ const {propertyOfProperty} = (await getObject()).property
· ────────────────────────────
╰────
help: When accessing a member from an await expression, the await expression has to be parenthesized, which is not readable.
⚠ eslint-plugin-unicorn(no-await-expression-member): Disallow member access from await expression
╭─[no_await_expression_member.tsx:1:1]
1 │ const {propertyOfProperty} = (await getObject()).propertyOfProperty
· ──────────────────────────────────────
╰────
help: When accessing a member from an await expression, the await expression has to be parenthesized, which is not readable.
⚠ eslint-plugin-unicorn(no-await-expression-member): Disallow member access from await expression
╭─[no_await_expression_member.tsx:1:1]
1 │ const [firstElementOfProperty] = (await getObject()).property
· ────────────────────────────
╰────
help: When accessing a member from an await expression, the await expression has to be parenthesized, which is not readable.
⚠ eslint-plugin-unicorn(no-await-expression-member): Disallow member access from await expression
╭─[no_await_expression_member.tsx:1:1]
1 │ const [firstElementOfProperty] = (await getObject()).firstElementOfProperty
· ──────────────────────────────────────────
╰────
help: When accessing a member from an await expression, the await expression has to be parenthesized, which is not readable.
⚠ eslint-plugin-unicorn(no-await-expression-member): Disallow member access from await expression
╭─[no_await_expression_member.tsx:1:1]
1 │ firstElement = (await getArray())[0]
· ─────────────────────
╰────
help: When accessing a member from an await expression, the await expression has to be parenthesized, which is not readable.
⚠ eslint-plugin-unicorn(no-await-expression-member): Disallow member access from await expression
╭─[no_await_expression_member.tsx:1:1]
1 │ property = (await getArray()).property
· ───────────────────────────
╰────
help: When accessing a member from an await expression, the await expression has to be parenthesized, which is not readable.
⚠ eslint-plugin-unicorn(no-await-expression-member): Disallow member access from await expression
╭─[no_await_expression_member.tsx:1:1]
1 │ const foo: Type = (await promise)[0]
· ──────────────────
╰────
help: When accessing a member from an await expression, the await expression has to be parenthesized, which is not readable.
⚠ eslint-plugin-unicorn(no-await-expression-member): Disallow member access from await expression
╭─[no_await_expression_member.tsx:1:1]
1 │ const foo: Type | A = (await promise).foo
· ───────────────────
╰────
help: When accessing a member from an await expression, the await expression has to be parenthesized, which is not readable.