perf(linter/unicorn/no-await-expression-member): optimize AST dispatch (#28348)

Rewrite rule to match on `AwaitExpression` first and then find the outer
expression, allowing for the rule to skip files that don't have `await`.

---

<sub>Stack created with <a
href="https://github.com/github/gh-stack">GitHub Stacks CLI</a> • <a
href="https://gh.io/stacks-feedback">Give Feedback 💬</a></sub>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Cam McHenryandCopilot authored and GitHub committed 2026-10-28 22:28:43 -04:00
1 parent 0c81934ba0
commit a3dc7a2aca
3 files changed
+17 -11

No files matched your search

+2 -5
View File
@@ -3321,11 +3321,8 @@ impl RuleRunner for crate::rules::unicorn::no_array_sort::NoArraySort {
}
impl RuleRunner for crate::rules::unicorn::no_await_expression_member::NoAwaitExpressionMember {
const NODE_TYPES: Option<&AstTypesBitset> = Some(&AstTypesBitset::from_types(&[
AstType::ComputedMemberExpression,
AstType::PrivateFieldExpression,
AstType::StaticMemberExpression,
]));
const NODE_TYPES: Option<&AstTypesBitset> =
Some(&AstTypesBitset::from_types(&[AstType::AwaitExpression]));
const RUN_FUNCTIONS: RuleRunFunctionsImplemented = RuleRunFunctionsImplemented::Run;
}
@@ -52,15 +52,21 @@ declare_oxc_lint!(
impl Rule for NoAwaitExpressionMember {
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
let AstKind::AwaitExpression(_) = node.kind() else {
return;
};
let parent = ctx.nodes().parent_node(node.id());
let AstKind::ParenthesizedExpression(paren_expr) = parent.kind() else {
return;
};
let node = ctx.nodes().parent_node(parent.id());
let Some(member_expr) = node.kind().as_member_expression_kind() else {
return;
};
let Expression::ParenthesizedExpression(paren_expr) = member_expr.object() else {
return;
};
if matches!(paren_expr.expression, Expression::AwaitExpression(_)) {
if member_expr.object().span() == paren_expr.span {
let node_span = member_expr.span();
ctx.diagnostic_with_dangerous_fix(
no_await_expression_member_diagnostic(node_span),
@@ -139,6 +145,8 @@ fn test() {
"const foo = typeof await promise",
"const foo = await notPromise.method()",
"const foo = foo[await promise]",
"const foo = foo[(await promise)]",
"const foo = ((await promise)).property",
// These await expression need parenthesized, but rarely used
"new (await promiseReturnsAClass)",
"(await promiseReturnsAFunction)()",
@@ -193,6 +201,7 @@ fn test() {
("const foo: Type = (await promise)[0]", "const foo: Type = (await promise)[0]"),
("const a = (await b())?.a", "const a = (await b())?.a"),
("const a = (await b())?.[0]", "const a = (await b())?.[0]"),
("const a = (await b())[(await key)]", "const a = (await b())[(await key)]"),
];
Tester::new(NoAwaitExpressionMember::NAME, NoAwaitExpressionMember::PLUGIN, pass, fail)
@@ -538,7 +538,7 @@ unicorn/no-array-method-this-argument | 62606
unicorn/no-array-reduce | 62606
unicorn/no-array-reverse | 62606
unicorn/no-array-sort | 62606
unicorn/no-await-expression-member | 95297
unicorn/no-await-expression-member | 231
unicorn/no-await-in-promise-methods | 62606
unicorn/no-confusing-array-with | 62606
unicorn/no-console-spaces | 62606