mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
feat(linter): eslint-plugin-unicorn no-await-expression-member (style) (#1569)
This commit is contained in:
parent
f7cb7838e5
commit
3b2b6a013a
3 changed files with 286 additions and 0 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
180
crates/oxc_linter/src/snapshots/no_await_expression_member.snap
Normal file
180
crates/oxc_linter/src/snapshots/no_await_expression_member.snap
Normal 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.
|
||||
|
||||
|
||||
Loading…
Reference in a new issue