@venizia/dev-configs 0.4.8-2 → 0.4.8-4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/dist/cli/codemod/async-style.d.ts +2 -2
- package/dist/cli/codemod/async-style.js +4 -2
- package/dist/cli/codemod/async-style.js.map +1 -1
- package/dist/cli/codemod/namespace-functions/rewriter.js +1 -1
- package/dist/cli/codemod/namespace-functions/rewriter.js.map +1 -1
- package/dist/linters/eslint.js +6 -1
- package/dist/linters/eslint.js.map +1 -1
- package/dist/linters/house/async-rules.d.ts +1 -1
- package/dist/linters/house/async-rules.js +3 -1
- package/dist/linters/house/async-rules.js.map +1 -1
- package/dist/linters/house/await-support.js +45 -38
- package/dist/linters/house/await-support.js.map +1 -1
- package/dist/linters/house/common.d.ts +43 -0
- package/dist/linters/house/common.js +43 -0
- package/dist/linters/house/common.js.map +1 -1
- package/dist/linters/house/const-class-values.rule.js +9 -8
- package/dist/linters/house/const-class-values.rule.js.map +1 -1
- package/dist/linters/house/hook-support.js +11 -7
- package/dist/linters/house/hook-support.js.map +1 -1
- package/dist/linters/house/index.d.ts +1 -0
- package/dist/linters/house/index.js +1 -0
- package/dist/linters/house/index.js.map +1 -1
- package/dist/linters/house/max-params-own.rule.js +12 -11
- package/dist/linters/house/max-params-own.rule.js.map +1 -1
- package/dist/linters/house/no-await-new-chain.rule.d.ts +37 -0
- package/dist/linters/house/no-await-new-chain.rule.js +179 -0
- package/dist/linters/house/no-await-new-chain.rule.js.map +1 -0
- package/dist/linters/house/no-await-promise-chain.rule.js +23 -22
- package/dist/linters/house/no-await-promise-chain.rule.js.map +1 -1
- package/dist/linters/house/no-inline-await.rule.js +4 -3
- package/dist/linters/house/no-inline-await.rule.js.map +1 -1
- package/dist/linters/house/no-leaked-render.rule.js +3 -3
- package/dist/linters/house/no-leaked-render.rule.js.map +1 -1
- package/dist/linters/house/no-new-error.rule.js +1 -1
- package/dist/linters/house/no-new-error.rule.js.map +1 -1
- package/dist/linters/house/no-return-await.rule.js +5 -4
- package/dist/linters/house/no-return-await.rule.js.map +1 -1
- package/dist/linters/house/no-silent-catch.rule.js +4 -3
- package/dist/linters/house/no-silent-catch.rule.js.map +1 -1
- package/dist/linters/house/plugin.js +2 -0
- package/dist/linters/house/plugin.js.map +1 -1
- package/dist/linters/house/promise-chain-support.js +25 -25
- package/dist/linters/house/promise-chain-support.js.map +1 -1
- package/dist/linters/oxlint.d.ts +6 -5
- package/dist/linters/oxlint.js +8 -3
- package/dist/linters/oxlint.js.map +1 -1
- package/package.json +1 -1
|
@@ -4,8 +4,8 @@ exports.AwaitSupport = exports.FUNCTION_TYPES = exports.STATEMENT_LISTS = void 0
|
|
|
4
4
|
const common_1 = require("./common");
|
|
5
5
|
exports.STATEMENT_LISTS = new Set([
|
|
6
6
|
common_1.AstNodeTypes.BLOCK_STATEMENT,
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
common_1.AstNodeTypes.PROGRAM,
|
|
8
|
+
common_1.AstNodeTypes.STATIC_BLOCK,
|
|
9
9
|
common_1.AstNodeTypes.SWITCH_CASE,
|
|
10
10
|
]);
|
|
11
11
|
exports.FUNCTION_TYPES = new Set([
|
|
@@ -25,23 +25,23 @@ const HEAD_FIELD = {
|
|
|
25
25
|
};
|
|
26
26
|
/** Nodes that evaluate to a value without doing anything else, so running them later or earlier changes nothing. */
|
|
27
27
|
const PURE_LEAVES = new Set([
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
common_1.AstNodeTypes.IDENTIFIER,
|
|
29
|
+
common_1.AstNodeTypes.LITERAL,
|
|
30
|
+
common_1.AstNodeTypes.THIS_EXPRESSION,
|
|
31
|
+
common_1.AstNodeTypes.ARROW_FUNCTION_EXPRESSION,
|
|
32
|
+
common_1.AstNodeTypes.FUNCTION_EXPRESSION,
|
|
33
|
+
common_1.AstNodeTypes.PRIVATE_IDENTIFIER,
|
|
34
34
|
]);
|
|
35
35
|
/** Wrappers whose parentheses around an `await` carry no meaning once the `await` is a name. */
|
|
36
36
|
const GROUPING_PARENTS = new Set([
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
37
|
+
common_1.AstNodeTypes.MEMBER_EXPRESSION,
|
|
38
|
+
common_1.AstNodeTypes.AS_EXPRESSION,
|
|
39
|
+
common_1.AstNodeTypes.SATISFIES_EXPRESSION,
|
|
40
|
+
common_1.AstNodeTypes.NON_NULL_EXPRESSION,
|
|
41
|
+
common_1.AstNodeTypes.UNARY_EXPRESSION,
|
|
42
|
+
common_1.AstNodeTypes.BINARY_EXPRESSION,
|
|
43
|
+
common_1.AstNodeTypes.SPREAD_ELEMENT,
|
|
44
|
+
common_1.AstNodeTypes.ARRAY_EXPRESSION,
|
|
45
45
|
]);
|
|
46
46
|
/** The shared parts of the two `await` rules: where a statement can go before another, what may run first, fresh names. */
|
|
47
47
|
class AwaitSupport {
|
|
@@ -69,29 +69,29 @@ class AwaitSupport {
|
|
|
69
69
|
let ancestor = AwaitSupport.parentOf({ node: child });
|
|
70
70
|
while (ancestor) {
|
|
71
71
|
const type = common_1.AstNode.getType({ node: ancestor }) ?? '';
|
|
72
|
-
if (exports.FUNCTION_TYPES.has(type) || type ===
|
|
72
|
+
if (exports.FUNCTION_TYPES.has(type) || type === common_1.AstNodeTypes.CHAIN_EXPRESSION) {
|
|
73
73
|
return undefined;
|
|
74
74
|
}
|
|
75
|
-
if (type ===
|
|
75
|
+
if (type === common_1.AstNodeTypes.CONDITIONAL_EXPRESSION &&
|
|
76
76
|
common_1.AstNode.readField({ node: ancestor, key: 'test' }) !== child) {
|
|
77
77
|
return undefined;
|
|
78
78
|
}
|
|
79
|
-
if (type ===
|
|
79
|
+
if (type === common_1.AstNodeTypes.LOGICAL_EXPRESSION &&
|
|
80
80
|
common_1.AstNode.readField({ node: ancestor, key: 'left' }) !== child) {
|
|
81
81
|
return undefined;
|
|
82
82
|
}
|
|
83
|
-
if (type ===
|
|
83
|
+
if (type === common_1.AstNodeTypes.ASSIGNMENT_EXPRESSION &&
|
|
84
84
|
['??=', '||=', '&&='].includes(String(common_1.AstNode.readField({ node: ancestor, key: 'operator' }))) &&
|
|
85
85
|
common_1.AstNode.readField({ node: ancestor, key: 'right' }) === child) {
|
|
86
86
|
return undefined;
|
|
87
87
|
}
|
|
88
|
-
if (type.endsWith('Statement') || type ===
|
|
88
|
+
if (type.endsWith('Statement') || type === common_1.AstNodeTypes.VARIABLE_DECLARATION) {
|
|
89
89
|
const head = HEAD_FIELD[type];
|
|
90
|
-
const isHead = type ===
|
|
90
|
+
const isHead = type === common_1.AstNodeTypes.VARIABLE_DECLARATION ||
|
|
91
91
|
common_1.AstNode.readField({ node: ancestor, key: head }) === child;
|
|
92
92
|
const outer = AwaitSupport.parentOf({ node: ancestor });
|
|
93
93
|
const isListed = exports.STATEMENT_LISTS.has(common_1.AstNode.getType({ node: outer }) ?? '') &&
|
|
94
|
-
(type ===
|
|
94
|
+
(type === common_1.AstNodeTypes.VARIABLE_DECLARATION || head !== undefined);
|
|
95
95
|
return isHead && isListed && AwaitSupport.isNode(ancestor) ? ancestor : undefined;
|
|
96
96
|
}
|
|
97
97
|
child = ancestor;
|
|
@@ -110,26 +110,33 @@ class AwaitSupport {
|
|
|
110
110
|
};
|
|
111
111
|
if (PURE_LEAVES.has(type) ||
|
|
112
112
|
(type.startsWith('TS') &&
|
|
113
|
-
![
|
|
113
|
+
![
|
|
114
|
+
common_1.AstNodeTypes.AS_EXPRESSION,
|
|
115
|
+
common_1.AstNodeTypes.NON_NULL_EXPRESSION,
|
|
116
|
+
common_1.AstNodeTypes.SATISFIES_EXPRESSION,
|
|
117
|
+
].includes(type))) {
|
|
114
118
|
return true;
|
|
115
119
|
}
|
|
116
120
|
const parts = new Map([
|
|
117
|
-
[
|
|
118
|
-
[
|
|
119
|
-
[
|
|
120
|
-
[
|
|
121
|
-
[
|
|
122
|
-
[
|
|
123
|
-
[
|
|
124
|
-
|
|
125
|
-
|
|
121
|
+
[common_1.AstNodeTypes.TEMPLATE_LITERAL, () => all('expressions')],
|
|
122
|
+
[common_1.AstNodeTypes.MEMBER_EXPRESSION, () => pure(field('object')) && pure(field('property'))],
|
|
123
|
+
[common_1.AstNodeTypes.ARRAY_EXPRESSION, () => all('elements')],
|
|
124
|
+
[common_1.AstNodeTypes.OBJECT_EXPRESSION, () => all('properties')],
|
|
125
|
+
[common_1.AstNodeTypes.PROPERTY, () => pure(field('key')) && pure(field('value'))],
|
|
126
|
+
[common_1.AstNodeTypes.SPREAD_ELEMENT, () => pure(field('argument'))],
|
|
127
|
+
[
|
|
128
|
+
common_1.AstNodeTypes.UNARY_EXPRESSION,
|
|
129
|
+
() => field('operator') !== 'delete' && pure(field('argument')),
|
|
130
|
+
],
|
|
131
|
+
[common_1.AstNodeTypes.BINARY_EXPRESSION, () => pure(field('left')) && pure(field('right'))],
|
|
132
|
+
[common_1.AstNodeTypes.LOGICAL_EXPRESSION, () => pure(field('left')) && pure(field('right'))],
|
|
126
133
|
[
|
|
127
|
-
|
|
134
|
+
common_1.AstNodeTypes.CONDITIONAL_EXPRESSION,
|
|
128
135
|
() => ['test', 'consequent', 'alternate'].every((key) => pure(field(key))),
|
|
129
136
|
],
|
|
130
|
-
[
|
|
131
|
-
[
|
|
132
|
-
[
|
|
137
|
+
[common_1.AstNodeTypes.AS_EXPRESSION, () => pure(field('expression'))],
|
|
138
|
+
[common_1.AstNodeTypes.NON_NULL_EXPRESSION, () => pure(field('expression'))],
|
|
139
|
+
[common_1.AstNodeTypes.SATISFIES_EXPRESSION, () => pure(field('expression'))],
|
|
133
140
|
]);
|
|
134
141
|
return parts.get(type)?.() ?? false;
|
|
135
142
|
}
|
|
@@ -228,7 +235,7 @@ class AwaitSupport {
|
|
|
228
235
|
const before = sourceCode.getTokenBefore(awaitNode);
|
|
229
236
|
const after = sourceCode.getTokenAfter(awaitNode);
|
|
230
237
|
const parentType = common_1.AstNode.getType({ node: AwaitSupport.parentOf({ node: awaitNode }) }) ?? '';
|
|
231
|
-
const callee = parentType ===
|
|
238
|
+
const callee = parentType === common_1.AstNodeTypes.CALL_EXPRESSION &&
|
|
232
239
|
common_1.AstNode.readField({ node: AwaitSupport.parentOf({ node: awaitNode }), key: 'callee' }) ===
|
|
233
240
|
awaitNode;
|
|
234
241
|
if (before?.value === '(' &&
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"await-support.js","sourceRoot":"","sources":["../../../src/linters/house/await-support.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Rule, SourceCode } from 'eslint';\nimport { AstNode, AstNodeTypes } from './common';\n\nexport const STATEMENT_LISTS = new Set<string>([\n AstNodeTypes.BLOCK_STATEMENT,\n 'Program',\n 'StaticBlock',\n AstNodeTypes.SWITCH_CASE,\n]);\nexport const FUNCTION_TYPES = new Set<string>([\n AstNodeTypes.FUNCTION_DECLARATION,\n AstNodeTypes.FUNCTION_EXPRESSION,\n AstNodeTypes.ARROW_FUNCTION_EXPRESSION,\n]);\n/** The child of a statement that runs exactly once, before anything else of that statement. */\nconst HEAD_FIELD: Record<string, string> = {\n IfStatement: 'test',\n SwitchStatement: 'discriminant',\n ForOfStatement: 'right',\n ForInStatement: 'right',\n ExpressionStatement: 'expression',\n ReturnStatement: 'argument',\n ThrowStatement: 'argument',\n};\n/** Nodes that evaluate to a value without doing anything else, so running them later or earlier changes nothing. */\nconst PURE_LEAVES = new Set([\n 'Identifier',\n 'Literal',\n 'ThisExpression',\n 'ArrowFunctionExpression',\n 'FunctionExpression',\n 'PrivateIdentifier',\n]);\n/** Wrappers whose parentheses around an `await` carry no meaning once the `await` is a name. */\nconst GROUPING_PARENTS = new Set([\n 'MemberExpression',\n 'TSAsExpression',\n 'TSSatisfiesExpression',\n 'TSNonNullExpression',\n 'UnaryExpression',\n 'BinaryExpression',\n 'SpreadElement',\n 'ArrayExpression',\n]);\n\n/** The shared parts of the two `await` rules: where a statement can go before another, what may run first, fresh names. */\nexport class AwaitSupport {\n static parentOf(opts: { node: unknown }): unknown {\n return AstNode.readField({ node: opts.node, key: 'parent' });\n }\n\n /** An ESTree node of the lint run: it has a `type` and a `range`. */\n static isNode(value: unknown): value is Rule.Node {\n return (\n AstNode.getType({ node: value }) !== undefined &&\n AwaitSupport.rangeOf({ node: value }) !== undefined\n );\n }\n\n static rangeOf(opts: { node: unknown }): [number, number] | undefined {\n const range = AstNode.readField({ node: opts.node, key: 'range' });\n\n return Array.isArray(range) && typeof range[0] === 'number' && typeof range[1] === 'number'\n ? [range[0], range[1]]\n : undefined;\n }\n\n /**\n * The statement that can take a `const` in front of it so that `awaitNode` is evaluated first, or `undefined`\n * when hoisting would change what runs: the `await` sits in a branch (`?:`, the right of `&&`, `||`, `??`),\n * in a loop test or update, in an unbraced `if` branch, in an optional chain, or in an arrow expression body.\n */\n static hoistTarget(opts: { awaitNode: unknown }): Rule.Node | undefined {\n let child: unknown = opts.awaitNode;\n let ancestor = AwaitSupport.parentOf({ node: child });\n\n while (ancestor) {\n const type = AstNode.getType({ node: ancestor }) ?? '';\n\n if (FUNCTION_TYPES.has(type) || type === 'ChainExpression') {\n return undefined;\n }\n\n if (\n type === 'ConditionalExpression' &&\n AstNode.readField({ node: ancestor, key: 'test' }) !== child\n ) {\n return undefined;\n }\n\n if (\n type === 'LogicalExpression' &&\n AstNode.readField({ node: ancestor, key: 'left' }) !== child\n ) {\n return undefined;\n }\n\n if (\n type === 'AssignmentExpression' &&\n ['??=', '||=', '&&='].includes(\n String(AstNode.readField({ node: ancestor, key: 'operator' })),\n ) &&\n AstNode.readField({ node: ancestor, key: 'right' }) === child\n ) {\n return undefined;\n }\n\n if (type.endsWith('Statement') || type === 'VariableDeclaration') {\n const head = HEAD_FIELD[type];\n const isHead =\n type === 'VariableDeclaration' ||\n AstNode.readField({ node: ancestor, key: head }) === child;\n const outer = AwaitSupport.parentOf({ node: ancestor });\n\n const isListed =\n STATEMENT_LISTS.has(AstNode.getType({ node: outer }) ?? '') &&\n (type === 'VariableDeclaration' || head !== undefined);\n\n return isHead && isListed && AwaitSupport.isNode(ancestor) ? ancestor : undefined;\n }\n\n child = ancestor;\n ancestor = AwaitSupport.parentOf({ node: child });\n }\n\n return undefined;\n }\n\n static isPure(opts: { node: unknown }): boolean {\n const { node } = opts;\n const type = AstNode.getType({ node }) ?? '';\n const pure = (child: unknown) => AwaitSupport.isPure({ node: child });\n const field = (key: string) => AstNode.readField({ node, key });\n\n const all = (key: string) => {\n const list = AstNode.readField({ node, key });\n\n return Array.isArray(list) && list.every((entry) => entry === null || pure(entry));\n };\n\n if (\n PURE_LEAVES.has(type) ||\n (type.startsWith('TS') &&\n !['TSAsExpression', 'TSNonNullExpression', 'TSSatisfiesExpression'].includes(type))\n ) {\n return true;\n }\n\n const parts = new Map<string, () => boolean>([\n ['TemplateLiteral', () => all('expressions')],\n ['MemberExpression', () => pure(field('object')) && pure(field('property'))],\n ['ArrayExpression', () => all('elements')],\n ['ObjectExpression', () => all('properties')],\n ['Property', () => pure(field('key')) && pure(field('value'))],\n ['SpreadElement', () => pure(field('argument'))],\n ['UnaryExpression', () => field('operator') !== 'delete' && pure(field('argument'))],\n ['BinaryExpression', () => pure(field('left')) && pure(field('right'))],\n ['LogicalExpression', () => pure(field('left')) && pure(field('right'))],\n [\n 'ConditionalExpression',\n () => ['test', 'consequent', 'alternate'].every((key) => pure(field(key))),\n ],\n ['TSAsExpression', () => pure(field('expression'))],\n ['TSNonNullExpression', () => pure(field('expression'))],\n ['TSSatisfiesExpression', () => pure(field('expression'))],\n ]);\n\n return parts.get(type)?.() ?? false;\n }\n\n /**\n * Whether something that does more than read a value runs, inside `statement`, before `awaitNode` does.\n * Hoisting the `await` in front of the statement would then run it first.\n */\n static hasEffectBefore(opts: {\n statement: Rule.Node;\n awaitNode: unknown;\n sourceCode: SourceCode;\n }): boolean {\n const target = AwaitSupport.rangeOf({ node: opts.awaitNode });\n\n if (!target) {\n return true;\n }\n\n const visit = (node: unknown): boolean => {\n const range = AwaitSupport.rangeOf({ node });\n\n if (!range) {\n return false;\n }\n\n if (range[0] <= target[0] && target[1] <= range[1]) {\n const keys = opts.sourceCode.visitorKeys[AstNode.getType({ node }) ?? ''] ?? [];\n\n return keys.some((key) => {\n const value = AstNode.readField({ node, key });\n const entries = Array.isArray(value) ? value : [value];\n\n return entries.some((entry) => entry && entry !== opts.awaitNode && visit(entry));\n });\n }\n\n return range[1] <= target[0] && !AwaitSupport.isPure({ node });\n };\n\n return visit(opts.statement);\n }\n\n /** The leading whitespace of the line a node starts on. */\n static indentOf(opts: { node: Rule.Node; sourceCode: SourceCode }): string {\n const line = opts.sourceCode.lines[(opts.node.loc?.start.line ?? 1) - 1] ?? '';\n\n return /^\\s*/.exec(line)?.[0] ?? '';\n }\n\n /** The nearest function or the program that holds `node`: the scope a new name must be free in. */\n static scopeNodeOf(opts: { node: Rule.Node }): Rule.Node {\n let current: Rule.Node = opts.node;\n let parent = AwaitSupport.parentOf({ node: current });\n\n while (parent && !FUNCTION_TYPES.has(AstNode.getType({ node: parent }) ?? '')) {\n if (!AwaitSupport.isNode(parent)) {\n break;\n }\n\n current = parent;\n parent = AwaitSupport.parentOf({ node: current });\n }\n\n return AwaitSupport.isNode(parent) ? parent : current;\n }\n\n /**\n * The outermost function that holds `node` (the program when no function does): the one namespace a hoisted name\n * must be unique in. A name that is free in the nearest function only could still shadow, or be shadowed by, the\n * name another fix hoisted in a function around it or a block inside it.\n */\n static outermostScopeOf(opts: { node: Rule.Node }): Rule.Node {\n let outermost: Rule.Node | undefined;\n let current: unknown = opts.node;\n\n while (AwaitSupport.isNode(current)) {\n if (FUNCTION_TYPES.has(AstNode.getType({ node: current }) ?? '')) {\n outermost = current;\n }\n\n current = AwaitSupport.parentOf({ node: current });\n }\n\n return outermost ?? AwaitSupport.scopeNodeOf({ node: opts.node });\n }\n\n /**\n * The names handed out in this lint pass, per outermost scope. They are shared by every rule that hoists a name: the\n * rules run in the same pass over the same text and their fixes are applied together, so two rules that each\n * remembered their own names both handed out `result`. A `SourceCode` lasts for one pass of one file.\n */\n private static readonly PASS_NAMES = new WeakMap<SourceCode, Map<unknown, Set<string>>>();\n\n /**\n * `base`, or `base2`, `base3`... the first word that does not appear in the outermost function (or program) holding\n * `node` and that no rule has handed out already in this lint pass: no two fixes of one pass declare the same name,\n * and none declares a name that is in scope anywhere around or inside the place it is hoisted to.\n */\n static freshName(opts: { node: Rule.Node; base: string; sourceCode: SourceCode }): string {\n const scope = AwaitSupport.outermostScopeOf({ node: opts.node });\n const text = opts.sourceCode.getText(scope);\n const pass = AwaitSupport.PASS_NAMES.get(opts.sourceCode) ?? new Map<unknown, Set<string>>();\n const reserved = pass.get(scope) ?? new Set<string>();\n\n AwaitSupport.PASS_NAMES.set(opts.sourceCode, pass);\n\n for (let index = 1; ; index += 1) {\n const candidate = index === 1 ? opts.base : `${opts.base}${index}`;\n\n if (!reserved.has(candidate) && !new RegExp(`\\\\b${candidate}\\\\b`).test(text)) {\n reserved.add(candidate);\n pass.set(scope, reserved);\n\n return candidate;\n }\n }\n }\n\n /**\n * The range to replace with the name that stands for an `await`: the `await` itself, widened over the parentheses\n * around it when they only grouped it (`(await f()).x`, `!(await f())`).\n */\n static replaceRangeOf(opts: { awaitNode: Rule.Node; sourceCode: SourceCode }): [number, number] {\n const { awaitNode, sourceCode } = opts;\n const before = sourceCode.getTokenBefore(awaitNode);\n const after = sourceCode.getTokenAfter(awaitNode);\n const parentType = AstNode.getType({ node: AwaitSupport.parentOf({ node: awaitNode }) }) ?? '';\n const callee =\n parentType === 'CallExpression' &&\n AstNode.readField({ node: AwaitSupport.parentOf({ node: awaitNode }), key: 'callee' }) ===\n awaitNode;\n\n if (\n before?.value === '(' &&\n after?.value === ')' &&\n (GROUPING_PARENTS.has(parentType) || callee)\n ) {\n return [before.range[0], after.range[1]];\n }\n\n return [awaitNode.range?.[0] ?? 0, awaitNode.range?.[1] ?? 0];\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"await-support.js","sourceRoot":"","sources":["../../../src/linters/house/await-support.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Rule, SourceCode } from 'eslint';\nimport { AstNode, AstNodeTypes } from './common';\n\nexport const STATEMENT_LISTS = new Set<string>([\n AstNodeTypes.BLOCK_STATEMENT,\n AstNodeTypes.PROGRAM,\n AstNodeTypes.STATIC_BLOCK,\n AstNodeTypes.SWITCH_CASE,\n]);\nexport const FUNCTION_TYPES = new Set<string>([\n AstNodeTypes.FUNCTION_DECLARATION,\n AstNodeTypes.FUNCTION_EXPRESSION,\n AstNodeTypes.ARROW_FUNCTION_EXPRESSION,\n]);\n/** The child of a statement that runs exactly once, before anything else of that statement. */\nconst HEAD_FIELD: Record<string, string> = {\n IfStatement: 'test',\n SwitchStatement: 'discriminant',\n ForOfStatement: 'right',\n ForInStatement: 'right',\n ExpressionStatement: 'expression',\n ReturnStatement: 'argument',\n ThrowStatement: 'argument',\n};\n/** Nodes that evaluate to a value without doing anything else, so running them later or earlier changes nothing. */\nconst PURE_LEAVES = new Set([\n AstNodeTypes.IDENTIFIER,\n AstNodeTypes.LITERAL,\n AstNodeTypes.THIS_EXPRESSION,\n AstNodeTypes.ARROW_FUNCTION_EXPRESSION,\n AstNodeTypes.FUNCTION_EXPRESSION,\n AstNodeTypes.PRIVATE_IDENTIFIER,\n]);\n/** Wrappers whose parentheses around an `await` carry no meaning once the `await` is a name. */\nconst GROUPING_PARENTS = new Set([\n AstNodeTypes.MEMBER_EXPRESSION,\n AstNodeTypes.AS_EXPRESSION,\n AstNodeTypes.SATISFIES_EXPRESSION,\n AstNodeTypes.NON_NULL_EXPRESSION,\n AstNodeTypes.UNARY_EXPRESSION,\n AstNodeTypes.BINARY_EXPRESSION,\n AstNodeTypes.SPREAD_ELEMENT,\n AstNodeTypes.ARRAY_EXPRESSION,\n]);\n\n/** The shared parts of the two `await` rules: where a statement can go before another, what may run first, fresh names. */\nexport class AwaitSupport {\n static parentOf(opts: { node: unknown }): unknown {\n return AstNode.readField({ node: opts.node, key: 'parent' });\n }\n\n /** An ESTree node of the lint run: it has a `type` and a `range`. */\n static isNode(value: unknown): value is Rule.Node {\n return (\n AstNode.getType({ node: value }) !== undefined &&\n AwaitSupport.rangeOf({ node: value }) !== undefined\n );\n }\n\n static rangeOf(opts: { node: unknown }): [number, number] | undefined {\n const range = AstNode.readField({ node: opts.node, key: 'range' });\n\n return Array.isArray(range) && typeof range[0] === 'number' && typeof range[1] === 'number'\n ? [range[0], range[1]]\n : undefined;\n }\n\n /**\n * The statement that can take a `const` in front of it so that `awaitNode` is evaluated first, or `undefined`\n * when hoisting would change what runs: the `await` sits in a branch (`?:`, the right of `&&`, `||`, `??`),\n * in a loop test or update, in an unbraced `if` branch, in an optional chain, or in an arrow expression body.\n */\n static hoistTarget(opts: { awaitNode: unknown }): Rule.Node | undefined {\n let child: unknown = opts.awaitNode;\n let ancestor = AwaitSupport.parentOf({ node: child });\n\n while (ancestor) {\n const type = AstNode.getType({ node: ancestor }) ?? '';\n\n if (FUNCTION_TYPES.has(type) || type === AstNodeTypes.CHAIN_EXPRESSION) {\n return undefined;\n }\n\n if (\n type === AstNodeTypes.CONDITIONAL_EXPRESSION &&\n AstNode.readField({ node: ancestor, key: 'test' }) !== child\n ) {\n return undefined;\n }\n\n if (\n type === AstNodeTypes.LOGICAL_EXPRESSION &&\n AstNode.readField({ node: ancestor, key: 'left' }) !== child\n ) {\n return undefined;\n }\n\n if (\n type === AstNodeTypes.ASSIGNMENT_EXPRESSION &&\n ['??=', '||=', '&&='].includes(\n String(AstNode.readField({ node: ancestor, key: 'operator' })),\n ) &&\n AstNode.readField({ node: ancestor, key: 'right' }) === child\n ) {\n return undefined;\n }\n\n if (type.endsWith('Statement') || type === AstNodeTypes.VARIABLE_DECLARATION) {\n const head = HEAD_FIELD[type];\n const isHead =\n type === AstNodeTypes.VARIABLE_DECLARATION ||\n AstNode.readField({ node: ancestor, key: head }) === child;\n const outer = AwaitSupport.parentOf({ node: ancestor });\n\n const isListed =\n STATEMENT_LISTS.has(AstNode.getType({ node: outer }) ?? '') &&\n (type === AstNodeTypes.VARIABLE_DECLARATION || head !== undefined);\n\n return isHead && isListed && AwaitSupport.isNode(ancestor) ? ancestor : undefined;\n }\n\n child = ancestor;\n ancestor = AwaitSupport.parentOf({ node: child });\n }\n\n return undefined;\n }\n\n static isPure(opts: { node: unknown }): boolean {\n const { node } = opts;\n const type = AstNode.getType({ node }) ?? '';\n const pure = (child: unknown) => AwaitSupport.isPure({ node: child });\n const field = (key: string) => AstNode.readField({ node, key });\n\n const all = (key: string) => {\n const list = AstNode.readField({ node, key });\n\n return Array.isArray(list) && list.every((entry) => entry === null || pure(entry));\n };\n\n if (\n PURE_LEAVES.has(type) ||\n (type.startsWith('TS') &&\n ![\n AstNodeTypes.AS_EXPRESSION,\n AstNodeTypes.NON_NULL_EXPRESSION,\n AstNodeTypes.SATISFIES_EXPRESSION,\n ].includes(type))\n ) {\n return true;\n }\n\n const parts = new Map<string, () => boolean>([\n [AstNodeTypes.TEMPLATE_LITERAL, () => all('expressions')],\n [AstNodeTypes.MEMBER_EXPRESSION, () => pure(field('object')) && pure(field('property'))],\n [AstNodeTypes.ARRAY_EXPRESSION, () => all('elements')],\n [AstNodeTypes.OBJECT_EXPRESSION, () => all('properties')],\n [AstNodeTypes.PROPERTY, () => pure(field('key')) && pure(field('value'))],\n [AstNodeTypes.SPREAD_ELEMENT, () => pure(field('argument'))],\n [\n AstNodeTypes.UNARY_EXPRESSION,\n () => field('operator') !== 'delete' && pure(field('argument')),\n ],\n [AstNodeTypes.BINARY_EXPRESSION, () => pure(field('left')) && pure(field('right'))],\n [AstNodeTypes.LOGICAL_EXPRESSION, () => pure(field('left')) && pure(field('right'))],\n [\n AstNodeTypes.CONDITIONAL_EXPRESSION,\n () => ['test', 'consequent', 'alternate'].every((key) => pure(field(key))),\n ],\n [AstNodeTypes.AS_EXPRESSION, () => pure(field('expression'))],\n [AstNodeTypes.NON_NULL_EXPRESSION, () => pure(field('expression'))],\n [AstNodeTypes.SATISFIES_EXPRESSION, () => pure(field('expression'))],\n ]);\n\n return parts.get(type)?.() ?? false;\n }\n\n /**\n * Whether something that does more than read a value runs, inside `statement`, before `awaitNode` does.\n * Hoisting the `await` in front of the statement would then run it first.\n */\n static hasEffectBefore(opts: {\n statement: Rule.Node;\n awaitNode: unknown;\n sourceCode: SourceCode;\n }): boolean {\n const target = AwaitSupport.rangeOf({ node: opts.awaitNode });\n\n if (!target) {\n return true;\n }\n\n const visit = (node: unknown): boolean => {\n const range = AwaitSupport.rangeOf({ node });\n\n if (!range) {\n return false;\n }\n\n if (range[0] <= target[0] && target[1] <= range[1]) {\n const keys = opts.sourceCode.visitorKeys[AstNode.getType({ node }) ?? ''] ?? [];\n\n return keys.some((key) => {\n const value = AstNode.readField({ node, key });\n const entries = Array.isArray(value) ? value : [value];\n\n return entries.some((entry) => entry && entry !== opts.awaitNode && visit(entry));\n });\n }\n\n return range[1] <= target[0] && !AwaitSupport.isPure({ node });\n };\n\n return visit(opts.statement);\n }\n\n /** The leading whitespace of the line a node starts on. */\n static indentOf(opts: { node: Rule.Node; sourceCode: SourceCode }): string {\n const line = opts.sourceCode.lines[(opts.node.loc?.start.line ?? 1) - 1] ?? '';\n\n return /^\\s*/.exec(line)?.[0] ?? '';\n }\n\n /** The nearest function or the program that holds `node`: the scope a new name must be free in. */\n static scopeNodeOf(opts: { node: Rule.Node }): Rule.Node {\n let current: Rule.Node = opts.node;\n let parent = AwaitSupport.parentOf({ node: current });\n\n while (parent && !FUNCTION_TYPES.has(AstNode.getType({ node: parent }) ?? '')) {\n if (!AwaitSupport.isNode(parent)) {\n break;\n }\n\n current = parent;\n parent = AwaitSupport.parentOf({ node: current });\n }\n\n return AwaitSupport.isNode(parent) ? parent : current;\n }\n\n /**\n * The outermost function that holds `node` (the program when no function does): the one namespace a hoisted name\n * must be unique in. A name that is free in the nearest function only could still shadow, or be shadowed by, the\n * name another fix hoisted in a function around it or a block inside it.\n */\n static outermostScopeOf(opts: { node: Rule.Node }): Rule.Node {\n let outermost: Rule.Node | undefined;\n let current: unknown = opts.node;\n\n while (AwaitSupport.isNode(current)) {\n if (FUNCTION_TYPES.has(AstNode.getType({ node: current }) ?? '')) {\n outermost = current;\n }\n\n current = AwaitSupport.parentOf({ node: current });\n }\n\n return outermost ?? AwaitSupport.scopeNodeOf({ node: opts.node });\n }\n\n /**\n * The names handed out in this lint pass, per outermost scope. They are shared by every rule that hoists a name: the\n * rules run in the same pass over the same text and their fixes are applied together, so two rules that each\n * remembered their own names both handed out `result`. A `SourceCode` lasts for one pass of one file.\n */\n private static readonly PASS_NAMES = new WeakMap<SourceCode, Map<unknown, Set<string>>>();\n\n /**\n * `base`, or `base2`, `base3`... the first word that does not appear in the outermost function (or program) holding\n * `node` and that no rule has handed out already in this lint pass: no two fixes of one pass declare the same name,\n * and none declares a name that is in scope anywhere around or inside the place it is hoisted to.\n */\n static freshName(opts: { node: Rule.Node; base: string; sourceCode: SourceCode }): string {\n const scope = AwaitSupport.outermostScopeOf({ node: opts.node });\n const text = opts.sourceCode.getText(scope);\n const pass = AwaitSupport.PASS_NAMES.get(opts.sourceCode) ?? new Map<unknown, Set<string>>();\n const reserved = pass.get(scope) ?? new Set<string>();\n\n AwaitSupport.PASS_NAMES.set(opts.sourceCode, pass);\n\n for (let index = 1; ; index += 1) {\n const candidate = index === 1 ? opts.base : `${opts.base}${index}`;\n\n if (!reserved.has(candidate) && !new RegExp(`\\\\b${candidate}\\\\b`).test(text)) {\n reserved.add(candidate);\n pass.set(scope, reserved);\n\n return candidate;\n }\n }\n }\n\n /**\n * The range to replace with the name that stands for an `await`: the `await` itself, widened over the parentheses\n * around it when they only grouped it (`(await f()).x`, `!(await f())`).\n */\n static replaceRangeOf(opts: { awaitNode: Rule.Node; sourceCode: SourceCode }): [number, number] {\n const { awaitNode, sourceCode } = opts;\n const before = sourceCode.getTokenBefore(awaitNode);\n const after = sourceCode.getTokenAfter(awaitNode);\n const parentType = AstNode.getType({ node: AwaitSupport.parentOf({ node: awaitNode }) }) ?? '';\n const callee =\n parentType === AstNodeTypes.CALL_EXPRESSION &&\n AstNode.readField({ node: AwaitSupport.parentOf({ node: awaitNode }), key: 'callee' }) ===\n awaitNode;\n\n if (\n before?.value === '(' &&\n after?.value === ')' &&\n (GROUPING_PARENTS.has(parentType) || callee)\n ) {\n return [before.range[0], after.range[1]];\n }\n\n return [awaitNode.range?.[0] ?? 0, awaitNode.range?.[1] ?? 0];\n }\n}\n"]}
|
|
@@ -12,6 +12,49 @@ export declare class AstNodeTypes {
|
|
|
12
12
|
static readonly CATCH_CLAUSE = "CatchClause";
|
|
13
13
|
static readonly SWITCH_CASE = "SwitchCase";
|
|
14
14
|
static readonly BLOCK_STATEMENT = "BlockStatement";
|
|
15
|
+
static readonly ARRAY_EXPRESSION = "ArrayExpression";
|
|
16
|
+
static readonly AS_EXPRESSION = "TSAsExpression";
|
|
17
|
+
static readonly ASSIGNMENT_EXPRESSION = "AssignmentExpression";
|
|
18
|
+
static readonly BINARY_EXPRESSION = "BinaryExpression";
|
|
19
|
+
static readonly CHAIN_EXPRESSION = "ChainExpression";
|
|
20
|
+
static readonly CONDITIONAL_EXPRESSION = "ConditionalExpression";
|
|
21
|
+
static readonly EMPTY_STATEMENT = "EmptyStatement";
|
|
22
|
+
static readonly EXPORT_DEFAULT_DECLARATION = "ExportDefaultDeclaration";
|
|
23
|
+
static readonly EXPORT_SPECIFIER = "ExportSpecifier";
|
|
24
|
+
static readonly EXPRESSION_STATEMENT = "ExpressionStatement";
|
|
25
|
+
static readonly IDENTIFIER = "Identifier";
|
|
26
|
+
static readonly JSX_ATTRIBUTE = "JSXAttribute";
|
|
27
|
+
static readonly JSX_ELEMENT = "JSXElement";
|
|
28
|
+
static readonly JSX_EXPRESSION_CONTAINER = "JSXExpressionContainer";
|
|
29
|
+
static readonly JSX_FRAGMENT = "JSXFragment";
|
|
30
|
+
static readonly LITERAL = "Literal";
|
|
31
|
+
static readonly LITERAL_TYPE = "TSLiteralType";
|
|
32
|
+
static readonly LOGICAL_EXPRESSION = "LogicalExpression";
|
|
33
|
+
static readonly MAPPED_TYPE = "TSMappedType";
|
|
34
|
+
static readonly MEMBER_EXPRESSION = "MemberExpression";
|
|
35
|
+
static readonly METHOD_DEFINITION = "MethodDefinition";
|
|
36
|
+
static readonly NON_NULL_EXPRESSION = "TSNonNullExpression";
|
|
37
|
+
static readonly NULL_KEYWORD = "TSNullKeyword";
|
|
38
|
+
static readonly OBJECT_EXPRESSION = "ObjectExpression";
|
|
39
|
+
static readonly PRIVATE_IDENTIFIER = "PrivateIdentifier";
|
|
40
|
+
static readonly PROGRAM = "Program";
|
|
41
|
+
static readonly PROPERTY = "Property";
|
|
42
|
+
static readonly SATISFIES_EXPRESSION = "TSSatisfiesExpression";
|
|
43
|
+
static readonly SEQUENCE_EXPRESSION = "SequenceExpression";
|
|
44
|
+
static readonly SPREAD_ELEMENT = "SpreadElement";
|
|
45
|
+
static readonly STATIC_BLOCK = "StaticBlock";
|
|
46
|
+
static readonly TEMPLATE_LITERAL = "TemplateLiteral";
|
|
47
|
+
static readonly THIS_EXPRESSION = "ThisExpression";
|
|
48
|
+
static readonly TRY_STATEMENT = "TryStatement";
|
|
49
|
+
static readonly TYPE_ALIAS_DECLARATION = "TSTypeAliasDeclaration";
|
|
50
|
+
static readonly TYPE_ASSERTION = "TSTypeAssertion";
|
|
51
|
+
static readonly TYPE_PARAMETER_INSTANTIATION = "TSTypeParameterInstantiation";
|
|
52
|
+
static readonly TYPE_QUERY = "TSTypeQuery";
|
|
53
|
+
static readonly TYPE_REFERENCE = "TSTypeReference";
|
|
54
|
+
static readonly UNARY_EXPRESSION = "UnaryExpression";
|
|
55
|
+
static readonly UNDEFINED_KEYWORD = "TSUndefinedKeyword";
|
|
56
|
+
static readonly VARIABLE_DECLARATION = "VariableDeclaration";
|
|
57
|
+
static readonly VARIABLE_DECLARATOR = "VariableDeclarator";
|
|
15
58
|
}
|
|
16
59
|
/** The ESLint namespace the house rules live under: `venizia/<rule>`. */
|
|
17
60
|
export declare const HOUSE_PLUGIN_NAMESPACE = "venizia";
|
|
@@ -15,6 +15,49 @@ class AstNodeTypes {
|
|
|
15
15
|
static { this.CATCH_CLAUSE = 'CatchClause'; }
|
|
16
16
|
static { this.SWITCH_CASE = 'SwitchCase'; }
|
|
17
17
|
static { this.BLOCK_STATEMENT = 'BlockStatement'; }
|
|
18
|
+
static { this.ARRAY_EXPRESSION = 'ArrayExpression'; }
|
|
19
|
+
static { this.AS_EXPRESSION = 'TSAsExpression'; }
|
|
20
|
+
static { this.ASSIGNMENT_EXPRESSION = 'AssignmentExpression'; }
|
|
21
|
+
static { this.BINARY_EXPRESSION = 'BinaryExpression'; }
|
|
22
|
+
static { this.CHAIN_EXPRESSION = 'ChainExpression'; }
|
|
23
|
+
static { this.CONDITIONAL_EXPRESSION = 'ConditionalExpression'; }
|
|
24
|
+
static { this.EMPTY_STATEMENT = 'EmptyStatement'; }
|
|
25
|
+
static { this.EXPORT_DEFAULT_DECLARATION = 'ExportDefaultDeclaration'; }
|
|
26
|
+
static { this.EXPORT_SPECIFIER = 'ExportSpecifier'; }
|
|
27
|
+
static { this.EXPRESSION_STATEMENT = 'ExpressionStatement'; }
|
|
28
|
+
static { this.IDENTIFIER = 'Identifier'; }
|
|
29
|
+
static { this.JSX_ATTRIBUTE = 'JSXAttribute'; }
|
|
30
|
+
static { this.JSX_ELEMENT = 'JSXElement'; }
|
|
31
|
+
static { this.JSX_EXPRESSION_CONTAINER = 'JSXExpressionContainer'; }
|
|
32
|
+
static { this.JSX_FRAGMENT = 'JSXFragment'; }
|
|
33
|
+
static { this.LITERAL = 'Literal'; }
|
|
34
|
+
static { this.LITERAL_TYPE = 'TSLiteralType'; }
|
|
35
|
+
static { this.LOGICAL_EXPRESSION = 'LogicalExpression'; }
|
|
36
|
+
static { this.MAPPED_TYPE = 'TSMappedType'; }
|
|
37
|
+
static { this.MEMBER_EXPRESSION = 'MemberExpression'; }
|
|
38
|
+
static { this.METHOD_DEFINITION = 'MethodDefinition'; }
|
|
39
|
+
static { this.NON_NULL_EXPRESSION = 'TSNonNullExpression'; }
|
|
40
|
+
static { this.NULL_KEYWORD = 'TSNullKeyword'; }
|
|
41
|
+
static { this.OBJECT_EXPRESSION = 'ObjectExpression'; }
|
|
42
|
+
static { this.PRIVATE_IDENTIFIER = 'PrivateIdentifier'; }
|
|
43
|
+
static { this.PROGRAM = 'Program'; }
|
|
44
|
+
static { this.PROPERTY = 'Property'; }
|
|
45
|
+
static { this.SATISFIES_EXPRESSION = 'TSSatisfiesExpression'; }
|
|
46
|
+
static { this.SEQUENCE_EXPRESSION = 'SequenceExpression'; }
|
|
47
|
+
static { this.SPREAD_ELEMENT = 'SpreadElement'; }
|
|
48
|
+
static { this.STATIC_BLOCK = 'StaticBlock'; }
|
|
49
|
+
static { this.TEMPLATE_LITERAL = 'TemplateLiteral'; }
|
|
50
|
+
static { this.THIS_EXPRESSION = 'ThisExpression'; }
|
|
51
|
+
static { this.TRY_STATEMENT = 'TryStatement'; }
|
|
52
|
+
static { this.TYPE_ALIAS_DECLARATION = 'TSTypeAliasDeclaration'; }
|
|
53
|
+
static { this.TYPE_ASSERTION = 'TSTypeAssertion'; }
|
|
54
|
+
static { this.TYPE_PARAMETER_INSTANTIATION = 'TSTypeParameterInstantiation'; }
|
|
55
|
+
static { this.TYPE_QUERY = 'TSTypeQuery'; }
|
|
56
|
+
static { this.TYPE_REFERENCE = 'TSTypeReference'; }
|
|
57
|
+
static { this.UNARY_EXPRESSION = 'UnaryExpression'; }
|
|
58
|
+
static { this.UNDEFINED_KEYWORD = 'TSUndefinedKeyword'; }
|
|
59
|
+
static { this.VARIABLE_DECLARATION = 'VariableDeclaration'; }
|
|
60
|
+
static { this.VARIABLE_DECLARATOR = 'VariableDeclarator'; }
|
|
18
61
|
}
|
|
19
62
|
exports.AstNodeTypes = AstNodeTypes;
|
|
20
63
|
/** The ESLint namespace the house rules live under: `venizia/<rule>`. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../../src/linters/house/common.ts"],"names":[],"mappings":";;;AAAA,8HAA8H;AAC9H,MAAa,YAAY;aACP,mBAAc,GAAG,eAAe,CAAC;aACjC,oBAAe,GAAG,gBAAgB,CAAC;aACnC,yBAAoB,GAAG,qBAAqB,CAAC;aAC7C,wBAAmB,GAAG,oBAAoB,CAAC;aAC3C,8BAAyB,GAAG,yBAAyB,CAAC;aACtD,6BAAwB,GAAG,wBAAwB,CAAC;aACpD,eAAU,GAAG,aAAa,CAAC;aAC3B,qBAAgB,GAAG,iBAAiB,CAAC;aACrC,qBAAgB,GAAG,iBAAiB,CAAC;aACrC,iBAAY,GAAG,aAAa,CAAC;aAC7B,gBAAW,GAAG,YAAY,CAAC;aAC3B,oBAAe,GAAG,gBAAgB,CAAC;;
|
|
1
|
+
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../../src/linters/house/common.ts"],"names":[],"mappings":"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","sourcesContent":["/** The estree node types the house rules visit - computed visitor keys, so the names stay PascalCase as ESLint needs them. */\nexport class AstNodeTypes {\n static readonly NEW_EXPRESSION = 'NewExpression';\n static readonly CALL_EXPRESSION = 'CallExpression';\n static readonly FUNCTION_DECLARATION = 'FunctionDeclaration';\n static readonly FUNCTION_EXPRESSION = 'FunctionExpression';\n static readonly ARROW_FUNCTION_EXPRESSION = 'ArrowFunctionExpression';\n static readonly EXPORT_NAMED_DECLARATION = 'ExportNamedDeclaration';\n static readonly UNION_TYPE = 'TSUnionType';\n static readonly AWAIT_EXPRESSION = 'AwaitExpression';\n static readonly RETURN_STATEMENT = 'ReturnStatement';\n static readonly CATCH_CLAUSE = 'CatchClause';\n static readonly SWITCH_CASE = 'SwitchCase';\n static readonly BLOCK_STATEMENT = 'BlockStatement';\n static readonly ARRAY_EXPRESSION = 'ArrayExpression';\n static readonly AS_EXPRESSION = 'TSAsExpression';\n static readonly ASSIGNMENT_EXPRESSION = 'AssignmentExpression';\n static readonly BINARY_EXPRESSION = 'BinaryExpression';\n static readonly CHAIN_EXPRESSION = 'ChainExpression';\n static readonly CONDITIONAL_EXPRESSION = 'ConditionalExpression';\n static readonly EMPTY_STATEMENT = 'EmptyStatement';\n static readonly EXPORT_DEFAULT_DECLARATION = 'ExportDefaultDeclaration';\n static readonly EXPORT_SPECIFIER = 'ExportSpecifier';\n static readonly EXPRESSION_STATEMENT = 'ExpressionStatement';\n static readonly IDENTIFIER = 'Identifier';\n static readonly JSX_ATTRIBUTE = 'JSXAttribute';\n static readonly JSX_ELEMENT = 'JSXElement';\n static readonly JSX_EXPRESSION_CONTAINER = 'JSXExpressionContainer';\n static readonly JSX_FRAGMENT = 'JSXFragment';\n static readonly LITERAL = 'Literal';\n static readonly LITERAL_TYPE = 'TSLiteralType';\n static readonly LOGICAL_EXPRESSION = 'LogicalExpression';\n static readonly MAPPED_TYPE = 'TSMappedType';\n static readonly MEMBER_EXPRESSION = 'MemberExpression';\n static readonly METHOD_DEFINITION = 'MethodDefinition';\n static readonly NON_NULL_EXPRESSION = 'TSNonNullExpression';\n static readonly NULL_KEYWORD = 'TSNullKeyword';\n static readonly OBJECT_EXPRESSION = 'ObjectExpression';\n static readonly PRIVATE_IDENTIFIER = 'PrivateIdentifier';\n static readonly PROGRAM = 'Program';\n static readonly PROPERTY = 'Property';\n static readonly SATISFIES_EXPRESSION = 'TSSatisfiesExpression';\n static readonly SEQUENCE_EXPRESSION = 'SequenceExpression';\n static readonly SPREAD_ELEMENT = 'SpreadElement';\n static readonly STATIC_BLOCK = 'StaticBlock';\n static readonly TEMPLATE_LITERAL = 'TemplateLiteral';\n static readonly THIS_EXPRESSION = 'ThisExpression';\n static readonly TRY_STATEMENT = 'TryStatement';\n static readonly TYPE_ALIAS_DECLARATION = 'TSTypeAliasDeclaration';\n static readonly TYPE_ASSERTION = 'TSTypeAssertion';\n static readonly TYPE_PARAMETER_INSTANTIATION = 'TSTypeParameterInstantiation';\n static readonly TYPE_QUERY = 'TSTypeQuery';\n static readonly TYPE_REFERENCE = 'TSTypeReference';\n static readonly UNARY_EXPRESSION = 'UnaryExpression';\n static readonly UNDEFINED_KEYWORD = 'TSUndefinedKeyword';\n static readonly VARIABLE_DECLARATION = 'VariableDeclaration';\n static readonly VARIABLE_DECLARATOR = 'VariableDeclarator';\n}\n\n/** The ESLint namespace the house rules live under: `venizia/<rule>`. */\nexport const HOUSE_PLUGIN_NAMESPACE = 'venizia';\n\n/** Reads an AST node without trusting its type: TypeScript nodes carry fields estree does not declare. */\nexport class AstNode {\n /** A field of an AST node. */\n static readField(opts: { node: unknown; key: string }): unknown {\n const { node, key } = opts;\n\n return typeof node === 'object' && node !== null && key in node\n ? Reflect.get(node, key)\n : undefined;\n }\n\n /** The node's `type`, or `undefined` for anything that is not an AST node. */\n static getType(opts: { node: unknown }): string | undefined {\n const type = AstNode.readField({ node: opts.node, key: 'type' });\n\n return typeof type === 'string' ? type : undefined;\n }\n}\n"]}
|
|
@@ -7,10 +7,10 @@ const KEY_SET_TYPES = new Set(['Pick', 'Omit', 'Extract', 'Exclude', 'Record']);
|
|
|
7
7
|
/** The union is a type argument of a key-set utility type, or the key range of a mapped type. */
|
|
8
8
|
const isKeySet = (opts) => {
|
|
9
9
|
const parent = common_1.AstNode.readField({ node: opts.node, key: 'parent' });
|
|
10
|
-
if (common_1.AstNode.getType({ node: parent }) ===
|
|
10
|
+
if (common_1.AstNode.getType({ node: parent }) === common_1.AstNodeTypes.MAPPED_TYPE) {
|
|
11
11
|
return true;
|
|
12
12
|
}
|
|
13
|
-
if (common_1.AstNode.getType({ node: parent }) !==
|
|
13
|
+
if (common_1.AstNode.getType({ node: parent }) !== common_1.AstNodeTypes.TYPE_PARAMETER_INSTANTIATION) {
|
|
14
14
|
return false;
|
|
15
15
|
}
|
|
16
16
|
const reference = common_1.AstNode.readField({ node: parent, key: 'parent' });
|
|
@@ -18,14 +18,15 @@ const isKeySet = (opts) => {
|
|
|
18
18
|
node: common_1.AstNode.readField({ node: reference, key: 'typeName' }),
|
|
19
19
|
key: 'name',
|
|
20
20
|
});
|
|
21
|
-
return (common_1.AstNode.getType({ node: reference }) ===
|
|
21
|
+
return (common_1.AstNode.getType({ node: reference }) === common_1.AstNodeTypes.TYPE_REFERENCE &&
|
|
22
|
+
KEY_SET_TYPES.has(String(name)));
|
|
22
23
|
};
|
|
23
24
|
/** The statement of the module that holds the node: the node's last ancestor before `Program`. */
|
|
24
25
|
const topLevelStatement = (opts) => {
|
|
25
26
|
let current = opts.node;
|
|
26
27
|
while (current) {
|
|
27
28
|
const parent = common_1.AstNode.readField({ node: current, key: 'parent' });
|
|
28
|
-
if (common_1.AstNode.getType({ node: parent }) ===
|
|
29
|
+
if (common_1.AstNode.getType({ node: parent }) === common_1.AstNodeTypes.PROGRAM) {
|
|
29
30
|
return current;
|
|
30
31
|
}
|
|
31
32
|
current = parent;
|
|
@@ -34,7 +35,7 @@ const topLevelStatement = (opts) => {
|
|
|
34
35
|
};
|
|
35
36
|
const isStringLiteral = (opts) => {
|
|
36
37
|
const { member } = opts;
|
|
37
|
-
return (common_1.AstNode.getType({ node: member }) ===
|
|
38
|
+
return (common_1.AstNode.getType({ node: member }) === common_1.AstNodeTypes.LITERAL_TYPE &&
|
|
38
39
|
typeof common_1.AstNode.readField({
|
|
39
40
|
node: common_1.AstNode.readField({ node: member, key: 'literal' }),
|
|
40
41
|
key: 'value',
|
|
@@ -42,7 +43,7 @@ const isStringLiteral = (opts) => {
|
|
|
42
43
|
};
|
|
43
44
|
const isNullish = (opts) => {
|
|
44
45
|
const type = common_1.AstNode.getType({ node: opts.member });
|
|
45
|
-
return type ===
|
|
46
|
+
return type === common_1.AstNodeTypes.NULL_KEYWORD || type === common_1.AstNodeTypes.UNDEFINED_KEYWORD;
|
|
46
47
|
};
|
|
47
48
|
/**
|
|
48
49
|
* `venizia/const-class-values`. An enumerable string is a const class plus `TConstValue<typeof X>`,
|
|
@@ -76,7 +77,7 @@ class ConstClassValuesRule {
|
|
|
76
77
|
key: 'name',
|
|
77
78
|
});
|
|
78
79
|
return (namePattern === undefined ||
|
|
79
|
-
(common_1.AstNode.getType({ node: declaration }) ===
|
|
80
|
+
(common_1.AstNode.getType({ node: declaration }) === common_1.AstNodeTypes.TYPE_ALIAS_DECLARATION &&
|
|
80
81
|
common_1.AstNode.readField({ node: declaration, key: 'typeAnnotation' }) === node &&
|
|
81
82
|
typeof name === 'string' &&
|
|
82
83
|
namePattern.test(name)));
|
|
@@ -94,7 +95,7 @@ class ConstClassValuesRule {
|
|
|
94
95
|
const statement = topLevelStatement({ node });
|
|
95
96
|
const statementType = common_1.AstNode.getType({ node: statement });
|
|
96
97
|
const isExported = statementType === common_1.AstNodeTypes.EXPORT_NAMED_DECLARATION ||
|
|
97
|
-
statementType ===
|
|
98
|
+
statementType === common_1.AstNodeTypes.EXPORT_DEFAULT_DECLARATION;
|
|
98
99
|
if (!isExported || isKeySet({ node }) || !isNamed({ statement, node })) {
|
|
99
100
|
return;
|
|
100
101
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"const-class-values.rule.js","sourceRoot":"","sources":["../../../src/linters/house/const-class-values.rule.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Linter, Rule } from 'eslint';\nimport type { TRuleSeverity } from '../rules/common';\nimport { AstNode, AstNodeTypes, HOUSE_PLUGIN_NAMESPACE } from './common';\n\n/** Utility types whose type argument is a set of keys, not an enumerable value: `Pick<T, 'a' | 'b'>`. */\nconst KEY_SET_TYPES = new Set(['Pick', 'Omit', 'Extract', 'Exclude', 'Record']);\n\n/** The union is a type argument of a key-set utility type, or the key range of a mapped type. */\nconst isKeySet = (opts: { node: unknown }): boolean => {\n const parent = AstNode.readField({ node: opts.node, key: 'parent' });\n\n if (AstNode.getType({ node: parent }) === 'TSMappedType') {\n return true;\n }\n\n if (AstNode.getType({ node: parent }) !== 'TSTypeParameterInstantiation') {\n return false;\n }\n\n const reference = AstNode.readField({ node: parent, key: 'parent' });\n const name = AstNode.readField({\n node: AstNode.readField({ node: reference, key: 'typeName' }),\n key: 'name',\n });\n\n return (\n AstNode.getType({ node: reference }) === 'TSTypeReference' && KEY_SET_TYPES.has(String(name))\n );\n};\n\n/** The statement of the module that holds the node: the node's last ancestor before `Program`. */\nconst topLevelStatement = (opts: { node: unknown }): unknown => {\n let current = opts.node;\n\n while (current) {\n const parent = AstNode.readField({ node: current, key: 'parent' });\n\n if (AstNode.getType({ node: parent }) === 'Program') {\n return current;\n }\n\n current = parent;\n }\n\n return undefined;\n};\n\nconst isStringLiteral = (opts: { member: unknown }): boolean => {\n const { member } = opts;\n\n return (\n AstNode.getType({ node: member }) === 'TSLiteralType' &&\n typeof AstNode.readField({\n node: AstNode.readField({ node: member, key: 'literal' }),\n key: 'value',\n }) === 'string'\n );\n};\n\nconst isNullish = (opts: { member: unknown }): boolean => {\n const type = AstNode.getType({ node: opts.member });\n\n return type === 'TSNullKeyword' || type === 'TSUndefinedKeyword';\n};\n\n/**\n * `venizia/const-class-values`. An enumerable string is a const class plus `TConstValue<typeof X>`,\n * never a union of string literals in an exported declaration: a type alias, an interface member, a\n * generic constraint, a parameter or a return type of an exported function or class.\n *\n * Not counted: a union that is not all string literals (a `null` or `undefined` member is ignored),\n * a key set (`Pick`, `Omit`, `Extract`, `Exclude`, `Record` arguments and mapped-type keys), and a\n * declaration that is not exported. `namePattern` narrows the rule to exported type aliases whose name\n * matches it (`(State|Status)$`), for a project that adopts the rule one name at a time.\n */\nexport class ConstClassValuesRule {\n static readonly NAME = `${HOUSE_PLUGIN_NAMESPACE}/const-class-values`;\n\n static readonly RULE: Rule.RuleModule = {\n meta: {\n type: 'suggestion',\n schema: [{ type: 'object', properties: { namePattern: { type: 'string' } } }],\n messages: {\n constClass:\n 'An enumerable string is a const class plus TConstValue<typeof X>, not a union of string literals.',\n },\n },\n create: (context) => {\n const options: unknown = context.options[0];\n const configured = AstNode.readField({ node: options, key: 'namePattern' });\n const namePattern = typeof configured === 'string' ? new RegExp(configured) : undefined;\n\n const isNamed = (opts: { statement: unknown; node: unknown }) => {\n const { statement, node } = opts;\n const declaration = AstNode.readField({ node: statement, key: 'declaration' });\n const name = AstNode.readField({\n node: AstNode.readField({ node: declaration, key: 'id' }),\n key: 'name',\n });\n\n return (\n namePattern === undefined ||\n (AstNode.getType({ node: declaration }) === 'TSTypeAliasDeclaration' &&\n AstNode.readField({ node: declaration, key: 'typeAnnotation' }) === node &&\n typeof name === 'string' &&\n namePattern.test(name))\n );\n };\n\n return {\n [AstNodeTypes.UNION_TYPE]: (node: Rule.Node) => {\n const members = AstNode.readField({ node, key: 'types' });\n\n if (!Array.isArray(members)) {\n return;\n }\n\n const values = members.filter((member) => !isNullish({ member }));\n\n if (values.length < 2 || !values.every((member) => isStringLiteral({ member }))) {\n return;\n }\n\n const statement = topLevelStatement({ node });\n const statementType = AstNode.getType({ node: statement });\n const isExported =\n statementType === AstNodeTypes.EXPORT_NAMED_DECLARATION ||\n statementType === 'ExportDefaultDeclaration';\n\n if (!isExported || isKeySet({ node }) || !isNamed({ statement, node })) {\n return;\n }\n\n context.report({ node, messageId: 'constClass' });\n },\n };\n },\n };\n\n static build(opts: { severity?: TRuleSeverity; namePattern?: string } = {}): Linter.RuleEntry {\n const { severity = 'error', namePattern } = opts;\n\n return namePattern === undefined ? [severity] : [severity, { namePattern }];\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"const-class-values.rule.js","sourceRoot":"","sources":["../../../src/linters/house/const-class-values.rule.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Linter, Rule } from 'eslint';\nimport type { TRuleSeverity } from '../rules/common';\nimport { AstNode, AstNodeTypes, HOUSE_PLUGIN_NAMESPACE } from './common';\n\n/** Utility types whose type argument is a set of keys, not an enumerable value: `Pick<T, 'a' | 'b'>`. */\nconst KEY_SET_TYPES = new Set(['Pick', 'Omit', 'Extract', 'Exclude', 'Record']);\n\n/** The union is a type argument of a key-set utility type, or the key range of a mapped type. */\nconst isKeySet = (opts: { node: unknown }): boolean => {\n const parent = AstNode.readField({ node: opts.node, key: 'parent' });\n\n if (AstNode.getType({ node: parent }) === AstNodeTypes.MAPPED_TYPE) {\n return true;\n }\n\n if (AstNode.getType({ node: parent }) !== AstNodeTypes.TYPE_PARAMETER_INSTANTIATION) {\n return false;\n }\n\n const reference = AstNode.readField({ node: parent, key: 'parent' });\n const name = AstNode.readField({\n node: AstNode.readField({ node: reference, key: 'typeName' }),\n key: 'name',\n });\n\n return (\n AstNode.getType({ node: reference }) === AstNodeTypes.TYPE_REFERENCE &&\n KEY_SET_TYPES.has(String(name))\n );\n};\n\n/** The statement of the module that holds the node: the node's last ancestor before `Program`. */\nconst topLevelStatement = (opts: { node: unknown }): unknown => {\n let current = opts.node;\n\n while (current) {\n const parent = AstNode.readField({ node: current, key: 'parent' });\n\n if (AstNode.getType({ node: parent }) === AstNodeTypes.PROGRAM) {\n return current;\n }\n\n current = parent;\n }\n\n return undefined;\n};\n\nconst isStringLiteral = (opts: { member: unknown }): boolean => {\n const { member } = opts;\n\n return (\n AstNode.getType({ node: member }) === AstNodeTypes.LITERAL_TYPE &&\n typeof AstNode.readField({\n node: AstNode.readField({ node: member, key: 'literal' }),\n key: 'value',\n }) === 'string'\n );\n};\n\nconst isNullish = (opts: { member: unknown }): boolean => {\n const type = AstNode.getType({ node: opts.member });\n\n return type === AstNodeTypes.NULL_KEYWORD || type === AstNodeTypes.UNDEFINED_KEYWORD;\n};\n\n/**\n * `venizia/const-class-values`. An enumerable string is a const class plus `TConstValue<typeof X>`,\n * never a union of string literals in an exported declaration: a type alias, an interface member, a\n * generic constraint, a parameter or a return type of an exported function or class.\n *\n * Not counted: a union that is not all string literals (a `null` or `undefined` member is ignored),\n * a key set (`Pick`, `Omit`, `Extract`, `Exclude`, `Record` arguments and mapped-type keys), and a\n * declaration that is not exported. `namePattern` narrows the rule to exported type aliases whose name\n * matches it (`(State|Status)$`), for a project that adopts the rule one name at a time.\n */\nexport class ConstClassValuesRule {\n static readonly NAME = `${HOUSE_PLUGIN_NAMESPACE}/const-class-values`;\n\n static readonly RULE: Rule.RuleModule = {\n meta: {\n type: 'suggestion',\n schema: [{ type: 'object', properties: { namePattern: { type: 'string' } } }],\n messages: {\n constClass:\n 'An enumerable string is a const class plus TConstValue<typeof X>, not a union of string literals.',\n },\n },\n create: (context) => {\n const options: unknown = context.options[0];\n const configured = AstNode.readField({ node: options, key: 'namePattern' });\n const namePattern = typeof configured === 'string' ? new RegExp(configured) : undefined;\n\n const isNamed = (opts: { statement: unknown; node: unknown }) => {\n const { statement, node } = opts;\n const declaration = AstNode.readField({ node: statement, key: 'declaration' });\n const name = AstNode.readField({\n node: AstNode.readField({ node: declaration, key: 'id' }),\n key: 'name',\n });\n\n return (\n namePattern === undefined ||\n (AstNode.getType({ node: declaration }) === AstNodeTypes.TYPE_ALIAS_DECLARATION &&\n AstNode.readField({ node: declaration, key: 'typeAnnotation' }) === node &&\n typeof name === 'string' &&\n namePattern.test(name))\n );\n };\n\n return {\n [AstNodeTypes.UNION_TYPE]: (node: Rule.Node) => {\n const members = AstNode.readField({ node, key: 'types' });\n\n if (!Array.isArray(members)) {\n return;\n }\n\n const values = members.filter((member) => !isNullish({ member }));\n\n if (values.length < 2 || !values.every((member) => isStringLiteral({ member }))) {\n return;\n }\n\n const statement = topLevelStatement({ node });\n const statementType = AstNode.getType({ node: statement });\n const isExported =\n statementType === AstNodeTypes.EXPORT_NAMED_DECLARATION ||\n statementType === AstNodeTypes.EXPORT_DEFAULT_DECLARATION;\n\n if (!isExported || isKeySet({ node }) || !isNamed({ statement, node })) {\n return;\n }\n\n context.report({ node, messageId: 'constClass' });\n },\n };\n },\n };\n\n static build(opts: { severity?: TRuleSeverity; namePattern?: string } = {}): Linter.RuleEntry {\n const { severity = 'error', namePattern } = opts;\n\n return namePattern === undefined ? [severity] : [severity, { namePattern }];\n }\n}\n"]}
|
|
@@ -4,22 +4,26 @@ exports.HookSupport = void 0;
|
|
|
4
4
|
const common_1 = require("./common");
|
|
5
5
|
const HOOK_NAME = /^use[A-Z]/;
|
|
6
6
|
const EFFECT_HOOKS = new Set(['useEffect', 'useLayoutEffect', 'useInsertionEffect']);
|
|
7
|
-
const CALLBACK_TYPES = new Set([
|
|
7
|
+
const CALLBACK_TYPES = new Set([
|
|
8
|
+
common_1.AstNodeTypes.ARROW_FUNCTION_EXPRESSION,
|
|
9
|
+
common_1.AstNodeTypes.FUNCTION_EXPRESSION,
|
|
10
|
+
]);
|
|
8
11
|
/** The shared parts of the two hook rules: which call is a hook, and which argument is a function. */
|
|
9
12
|
class HookSupport {
|
|
10
13
|
/** `useX(...)` and `React.useX(...)`: the name the call is made through, or `undefined` when it is not a plain name. */
|
|
11
14
|
static calleeName(opts) {
|
|
12
15
|
const callee = common_1.AstNode.readField({ node: opts.call, key: 'callee' });
|
|
13
16
|
const type = common_1.AstNode.getType({ node: callee });
|
|
14
|
-
if (type ===
|
|
17
|
+
if (type === common_1.AstNodeTypes.IDENTIFIER) {
|
|
15
18
|
const name = common_1.AstNode.readField({ node: callee, key: 'name' });
|
|
16
19
|
return typeof name === 'string' ? name : undefined;
|
|
17
20
|
}
|
|
18
|
-
if (type ===
|
|
21
|
+
if (type === common_1.AstNodeTypes.MEMBER_EXPRESSION &&
|
|
19
22
|
common_1.AstNode.readField({ node: callee, key: 'computed' }) === false) {
|
|
20
23
|
const property = common_1.AstNode.readField({ node: callee, key: 'property' });
|
|
21
24
|
const name = common_1.AstNode.readField({ node: property, key: 'name' });
|
|
22
|
-
return common_1.AstNode.getType({ node: property }) ===
|
|
25
|
+
return common_1.AstNode.getType({ node: property }) === common_1.AstNodeTypes.IDENTIFIER &&
|
|
26
|
+
typeof name === 'string'
|
|
23
27
|
? name
|
|
24
28
|
: undefined;
|
|
25
29
|
}
|
|
@@ -49,17 +53,17 @@ class HookSupport {
|
|
|
49
53
|
if (HookSupport.isAsync({ node })) {
|
|
50
54
|
return [node];
|
|
51
55
|
}
|
|
52
|
-
if (type ===
|
|
56
|
+
if (type === common_1.AstNodeTypes.OBJECT_EXPRESSION) {
|
|
53
57
|
const properties = common_1.AstNode.readField({ node, key: 'properties' });
|
|
54
58
|
return Array.isArray(properties)
|
|
55
|
-
? properties.flatMap((property) => common_1.AstNode.getType({ node: property }) ===
|
|
59
|
+
? properties.flatMap((property) => common_1.AstNode.getType({ node: property }) === common_1.AstNodeTypes.PROPERTY
|
|
56
60
|
? HookSupport.asyncFunctionsIn({
|
|
57
61
|
node: common_1.AstNode.readField({ node: property, key: 'value' }),
|
|
58
62
|
})
|
|
59
63
|
: [])
|
|
60
64
|
: [];
|
|
61
65
|
}
|
|
62
|
-
if (type ===
|
|
66
|
+
if (type === common_1.AstNodeTypes.ARRAY_EXPRESSION) {
|
|
63
67
|
const elements = common_1.AstNode.readField({ node, key: 'elements' });
|
|
64
68
|
return Array.isArray(elements)
|
|
65
69
|
? elements.flatMap((element) => HookSupport.asyncFunctionsIn({ node: element }))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hook-support.js","sourceRoot":"","sources":["../../../src/linters/house/hook-support.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"hook-support.js","sourceRoot":"","sources":["../../../src/linters/house/hook-support.ts"],"names":[],"mappings":"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","sourcesContent":["import { AstNode, AstNodeTypes } from './common';\n\nconst HOOK_NAME = /^use[A-Z]/;\nconst EFFECT_HOOKS = new Set(['useEffect', 'useLayoutEffect', 'useInsertionEffect']);\nconst CALLBACK_TYPES = new Set([\n AstNodeTypes.ARROW_FUNCTION_EXPRESSION,\n AstNodeTypes.FUNCTION_EXPRESSION,\n]);\n\n/** The shared parts of the two hook rules: which call is a hook, and which argument is a function. */\nexport class HookSupport {\n /** `useX(...)` and `React.useX(...)`: the name the call is made through, or `undefined` when it is not a plain name. */\n static calleeName(opts: { call: unknown }): string | undefined {\n const callee = AstNode.readField({ node: opts.call, key: 'callee' });\n const type = AstNode.getType({ node: callee });\n\n if (type === AstNodeTypes.IDENTIFIER) {\n const name = AstNode.readField({ node: callee, key: 'name' });\n\n return typeof name === 'string' ? name : undefined;\n }\n\n if (\n type === AstNodeTypes.MEMBER_EXPRESSION &&\n AstNode.readField({ node: callee, key: 'computed' }) === false\n ) {\n const property = AstNode.readField({ node: callee, key: 'property' });\n const name = AstNode.readField({ node: property, key: 'name' });\n\n return AstNode.getType({ node: property }) === AstNodeTypes.IDENTIFIER &&\n typeof name === 'string'\n ? name\n : undefined;\n }\n\n return undefined;\n }\n\n static isHook(opts: { name: string | undefined }): boolean {\n return opts.name !== undefined && HOOK_NAME.test(opts.name);\n }\n\n static isEffectHook(opts: { name: string | undefined }): boolean {\n return opts.name !== undefined && EFFECT_HOOKS.has(opts.name);\n }\n\n /** An arrow or a function expression: the two forms a hook callback is written in. */\n static isCallback(opts: { node: unknown }): boolean {\n return CALLBACK_TYPES.has(AstNode.getType({ node: opts.node }) ?? '');\n }\n\n static isAsync(opts: { node: unknown }): boolean {\n return (\n HookSupport.isCallback(opts) && AstNode.readField({ node: opts.node, key: 'async' }) === true\n );\n }\n\n /**\n * The async functions an argument hands over: the argument itself, a property value of an object literal\n * (`useMutation({ mutationFn: async () => {} })`, an async method too) and an element of an array literal, at any\n * depth of literals. It does not look inside a function: what a sync callback builds is not an argument.\n */\n static asyncFunctionsIn(opts: { node: unknown }): unknown[] {\n const { node } = opts;\n const type = AstNode.getType({ node });\n\n if (HookSupport.isAsync({ node })) {\n return [node];\n }\n\n if (type === AstNodeTypes.OBJECT_EXPRESSION) {\n const properties = AstNode.readField({ node, key: 'properties' });\n\n return Array.isArray(properties)\n ? properties.flatMap((property) =>\n AstNode.getType({ node: property }) === AstNodeTypes.PROPERTY\n ? HookSupport.asyncFunctionsIn({\n node: AstNode.readField({ node: property, key: 'value' }),\n })\n : [],\n )\n : [];\n }\n\n if (type === AstNodeTypes.ARRAY_EXPRESSION) {\n const elements = AstNode.readField({ node, key: 'elements' });\n\n return Array.isArray(elements)\n ? elements.flatMap((element) => HookSupport.asyncFunctionsIn({ node: element }))\n : [];\n }\n\n return [];\n }\n}\n"]}
|
|
@@ -5,6 +5,7 @@ export * from './effect-cleanup-consistency.rule';
|
|
|
5
5
|
export * from './hook-support';
|
|
6
6
|
export * from './max-params-own.rule';
|
|
7
7
|
export * from './no-async-hook-callback.rule';
|
|
8
|
+
export * from './no-await-new-chain.rule';
|
|
8
9
|
export * from './no-await-promise-chain.rule';
|
|
9
10
|
export * from './no-inline-await.rule';
|
|
10
11
|
export * from './no-leaked-render.rule';
|
|
@@ -23,6 +23,7 @@ __exportStar(require("./effect-cleanup-consistency.rule"), exports);
|
|
|
23
23
|
__exportStar(require("./hook-support"), exports);
|
|
24
24
|
__exportStar(require("./max-params-own.rule"), exports);
|
|
25
25
|
__exportStar(require("./no-async-hook-callback.rule"), exports);
|
|
26
|
+
__exportStar(require("./no-await-new-chain.rule"), exports);
|
|
26
27
|
__exportStar(require("./no-await-promise-chain.rule"), exports);
|
|
27
28
|
__exportStar(require("./no-inline-await.rule"), exports);
|
|
28
29
|
__exportStar(require("./no-leaked-render.rule"), exports);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/linters/house/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,iDAA+C;AAAtC,6GAAA,YAAY,OAAA;AACrB,2CAAyB;AACzB,4DAA0C;AAC1C,oEAAkD;AAClD,iDAA+B;AAC/B,wDAAsC;AACtC,gEAA8C;AAC9C,gEAA8C;AAC9C,yDAAuC;AACvC,0DAAwC;AACxC,sDAAoC;AACpC,yDAAuC;AACvC,yDAAuC;AACvC,0DAAwC;AACxC,2CAAyB;AACzB,0DAAwC;AACxC,4CAA0B","sourcesContent":["export { AwaitSupport } from './await-support';\nexport * from './common';\nexport * from './const-class-values.rule';\nexport * from './effect-cleanup-consistency.rule';\nexport * from './hook-support';\nexport * from './max-params-own.rule';\nexport * from './no-async-hook-callback.rule';\nexport * from './no-await-promise-chain.rule';\nexport * from './no-inline-await.rule';\nexport * from './no-leaked-render.rule';\nexport * from './no-new-error.rule';\nexport * from './no-return-await.rule';\nexport * from './no-silent-catch.rule';\nexport * from './no-unbraced-case.rule';\nexport * from './plugin';\nexport * from './promise-chain-support';\nexport * from './configs';\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/linters/house/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,iDAA+C;AAAtC,6GAAA,YAAY,OAAA;AACrB,2CAAyB;AACzB,4DAA0C;AAC1C,oEAAkD;AAClD,iDAA+B;AAC/B,wDAAsC;AACtC,gEAA8C;AAC9C,4DAA0C;AAC1C,gEAA8C;AAC9C,yDAAuC;AACvC,0DAAwC;AACxC,sDAAoC;AACpC,yDAAuC;AACvC,yDAAuC;AACvC,0DAAwC;AACxC,2CAAyB;AACzB,0DAAwC;AACxC,4CAA0B","sourcesContent":["export { AwaitSupport } from './await-support';\nexport * from './common';\nexport * from './const-class-values.rule';\nexport * from './effect-cleanup-consistency.rule';\nexport * from './hook-support';\nexport * from './max-params-own.rule';\nexport * from './no-async-hook-callback.rule';\nexport * from './no-await-new-chain.rule';\nexport * from './no-await-promise-chain.rule';\nexport * from './no-inline-await.rule';\nexport * from './no-leaked-render.rule';\nexport * from './no-new-error.rule';\nexport * from './no-return-await.rule';\nexport * from './no-silent-catch.rule';\nexport * from './no-unbraced-case.rule';\nexport * from './plugin';\nexport * from './promise-chain-support';\nexport * from './configs';\n"]}
|