Skip to content

Commit 55e31ad

Browse files
committed
feat(no-top-level-await): new rule
1 parent 4698633 commit 55e31ad

File tree

3 files changed

+79
-0
lines changed

3 files changed

+79
-0
lines changed

src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import importDedupe from './rules/import-dedupe'
88
import indentUnindent from './rules/indent-unindent'
99
import noImportDist from './rules/no-import-dist'
1010
import noImportNodeModulesByPath from './rules/no-import-node-modules-by-path'
11+
import noTopLevelAwait from './rules/no-top-level-await'
1112
import noTsExportEqual from './rules/no-ts-export-equal'
1213
import topLevelFunction from './rules/top-level-function'
1314

@@ -26,6 +27,7 @@ const plugin = {
2627
'indent-unindent': indentUnindent,
2728
'no-import-dist': noImportDist,
2829
'no-import-node-modules-by-path': noImportNodeModulesByPath,
30+
'no-top-level-await': noTopLevelAwait,
2931
'no-ts-export-equal': noTsExportEqual,
3032
'top-level-function': topLevelFunction,
3133
},
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { unindent as $ } from 'eslint-vitest-rule-tester'
2+
import { run } from './_test'
3+
import rule, { RULE_NAME } from './no-top-level-await'
4+
5+
const valids = [
6+
'async function foo() { await bar() }',
7+
$`
8+
const a = async () => {
9+
await bar()
10+
}
11+
`,
12+
]
13+
14+
const invalids = [
15+
'await foo()',
16+
17+
$`
18+
function foo() {
19+
20+
}
21+
22+
await foo()
23+
`,
24+
$`
25+
const a = {
26+
foo: await bar()
27+
}
28+
`,
29+
]
30+
31+
run({
32+
name: RULE_NAME,
33+
rule,
34+
valid: valids,
35+
invalid: invalids.map(i => ({
36+
code: i,
37+
errors: [{ messageId: 'NoTopLevelAwait' }],
38+
})),
39+
})

src/rules/no-top-level-await.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import type { TSESTree } from '@typescript-eslint/utils'
2+
import { createEslintRule } from '../utils'
3+
4+
export const RULE_NAME = 'no-top-level-await'
5+
export type MessageIds = 'NoTopLevelAwait'
6+
export type Options = []
7+
8+
export default createEslintRule<Options, MessageIds>({
9+
name: RULE_NAME,
10+
meta: {
11+
type: 'problem',
12+
docs: {
13+
description: 'Prevent using top-level await',
14+
},
15+
schema: [],
16+
messages: {
17+
NoTopLevelAwait: 'Do not use top-level await',
18+
},
19+
},
20+
defaultOptions: [],
21+
create: (context) => {
22+
return {
23+
AwaitExpression: (node) => {
24+
let parent: TSESTree.Node | undefined = node.parent
25+
while (parent) {
26+
if (parent.type === 'FunctionDeclaration' || parent.type === 'FunctionExpression' || parent.type === 'ArrowFunctionExpression') {
27+
return
28+
}
29+
parent = parent.parent
30+
}
31+
context.report({
32+
node,
33+
messageId: 'NoTopLevelAwait',
34+
})
35+
},
36+
}
37+
},
38+
})

0 commit comments

Comments
 (0)