@venizia/dev-configs 0.4.8-3 → 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/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/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.js +15 -13
- package/dist/linters/house/no-await-new-chain.rule.js.map +1 -1
- 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/promise-chain-support.js +25 -25
- package/dist/linters/house/promise-chain-support.js.map +1 -1
- package/package.json +1 -1
|
@@ -3,13 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.MaxParamsOwnRule = void 0;
|
|
4
4
|
const common_1 = require("./common");
|
|
5
5
|
const HOOK_NAME = /^use[A-Z]/;
|
|
6
|
-
const CALL_TYPES = new Set([
|
|
6
|
+
const CALL_TYPES = new Set([common_1.AstNodeTypes.CALL_EXPRESSION, common_1.AstNodeTypes.NEW_EXPRESSION]);
|
|
7
7
|
const isArrayContaining = (opts) => Array.isArray(opts.list) && opts.list.includes(opts.item);
|
|
8
8
|
/** `useX(...)`: a hook's callback is ours, so it counts. */
|
|
9
9
|
const isHookCall = (call) => {
|
|
10
10
|
const callee = common_1.AstNode.readField({ node: call, key: 'callee' });
|
|
11
11
|
const name = common_1.AstNode.readField({ node: callee, key: 'name' });
|
|
12
|
-
return (common_1.AstNode.getType({ node: callee }) ===
|
|
12
|
+
return (common_1.AstNode.getType({ node: callee }) === common_1.AstNodeTypes.IDENTIFIER &&
|
|
13
13
|
typeof name === 'string' &&
|
|
14
14
|
HOOK_NAME.test(name));
|
|
15
15
|
};
|
|
@@ -29,17 +29,18 @@ const hasDeclaredShape = (object) => {
|
|
|
29
29
|
while (current) {
|
|
30
30
|
const parent = common_1.AstNode.readField({ node: current, key: 'parent' });
|
|
31
31
|
const parentType = common_1.AstNode.getType({ node: parent });
|
|
32
|
-
const isTypedVariable = parentType ===
|
|
32
|
+
const isTypedVariable = parentType === common_1.AstNodeTypes.VARIABLE_DECLARATOR &&
|
|
33
33
|
Boolean(common_1.AstNode.readField({
|
|
34
34
|
node: common_1.AstNode.readField({ node: parent, key: 'id' }),
|
|
35
35
|
key: 'typeAnnotation',
|
|
36
36
|
}));
|
|
37
37
|
if (isTypedVariable ||
|
|
38
|
-
parentType ===
|
|
38
|
+
parentType === common_1.AstNodeTypes.SATISFIES_EXPRESSION ||
|
|
39
39
|
isLibraryArgument({ node: current, parent })) {
|
|
40
40
|
return true;
|
|
41
41
|
}
|
|
42
|
-
const isNestedValue = parentType ===
|
|
42
|
+
const isNestedValue = parentType === common_1.AstNodeTypes.PROPERTY &&
|
|
43
|
+
common_1.AstNode.readField({ node: parent, key: 'value' }) === current;
|
|
43
44
|
current = isNestedValue ? common_1.AstNode.readField({ node: parent, key: 'parent' }) : undefined;
|
|
44
45
|
}
|
|
45
46
|
return false;
|
|
@@ -66,9 +67,9 @@ class MaxParamsOwnRule {
|
|
|
66
67
|
const max = typeof context.options[0] === 'number' ? context.options[0] : MaxParamsOwnRule.DEFAULT_MAX;
|
|
67
68
|
const isCallback = (node) => {
|
|
68
69
|
const parent = node.parent;
|
|
69
|
-
const isJsxProp = common_1.AstNode.getType({ node: parent }) ===
|
|
70
|
+
const isJsxProp = common_1.AstNode.getType({ node: parent }) === common_1.AstNodeTypes.JSX_EXPRESSION_CONTAINER &&
|
|
70
71
|
common_1.AstNode.getType({ node: common_1.AstNode.readField({ node: parent, key: 'parent' }) }) ===
|
|
71
|
-
|
|
72
|
+
common_1.AstNodeTypes.JSX_ATTRIBUTE;
|
|
72
73
|
return isJsxProp || isLibraryArgument({ node, parent });
|
|
73
74
|
};
|
|
74
75
|
const isInjectedConstructor = (opts) => {
|
|
@@ -82,23 +83,23 @@ class MaxParamsOwnRule {
|
|
|
82
83
|
return ((Array.isArray(own) && own.length > 0) ||
|
|
83
84
|
(Array.isArray(property) && property.length > 0));
|
|
84
85
|
};
|
|
85
|
-
return (common_1.AstNode.getType({ node: parent }) ===
|
|
86
|
+
return (common_1.AstNode.getType({ node: parent }) === common_1.AstNodeTypes.METHOD_DEFINITION &&
|
|
86
87
|
common_1.AstNode.readField({ node: parent, key: 'kind' }) === 'constructor' &&
|
|
87
88
|
opts.params.every(isDecorated));
|
|
88
89
|
};
|
|
89
90
|
const isTypedByContext = (node) => {
|
|
90
91
|
const parent = node.parent;
|
|
91
92
|
const parentType = common_1.AstNode.getType({ node: parent });
|
|
92
|
-
const isTypedInit = parentType ===
|
|
93
|
+
const isTypedInit = parentType === common_1.AstNodeTypes.VARIABLE_DECLARATOR &&
|
|
93
94
|
common_1.AstNode.readField({ node: parent, key: 'init' }) === node &&
|
|
94
95
|
Boolean(common_1.AstNode.readField({
|
|
95
96
|
node: common_1.AstNode.readField({ node: parent, key: 'id' }),
|
|
96
97
|
key: 'typeAnnotation',
|
|
97
98
|
}));
|
|
98
99
|
const grandParent = common_1.AstNode.readField({ node: parent, key: 'parent' });
|
|
99
|
-
const isMember = parentType ===
|
|
100
|
+
const isMember = parentType === common_1.AstNodeTypes.PROPERTY &&
|
|
100
101
|
common_1.AstNode.readField({ node: parent, key: 'value' }) === node &&
|
|
101
|
-
common_1.AstNode.getType({ node: grandParent }) ===
|
|
102
|
+
common_1.AstNode.getType({ node: grandParent }) === common_1.AstNodeTypes.OBJECT_EXPRESSION;
|
|
102
103
|
return isTypedInit || (isMember && hasDeclaredShape(grandParent));
|
|
103
104
|
};
|
|
104
105
|
const check = (node) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"max-params-own.rule.js","sourceRoot":"","sources":["../../../src/linters/house/max-params-own.rule.ts"],"names":[],"mappings":";;;AAEA,qCAAyE;AAEzE,MAAM,SAAS,GAAG,WAAW,CAAC;AAC9B,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,CAAC,gBAAgB,EAAE,eAAe,CAAC,CAAC,CAAC;AAEhE,MAAM,iBAAiB,GAAG,CAAC,IAAsC,EAAE,EAAE,CACnE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAE5D,4DAA4D;AAC5D,MAAM,UAAU,GAAG,CAAC,IAAa,EAAE,EAAE;IACnC,MAAM,MAAM,GAAG,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;IAChE,MAAM,IAAI,GAAG,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC;IAE9D,OAAO,CACL,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,KAAK,YAAY;QAClD,OAAO,IAAI,KAAK,QAAQ;QACxB,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CACrB,CAAC;AACJ,CAAC,CAAC;AAEF,mEAAmE;AACnE,MAAM,iBAAiB,GAAG,CAAC,IAAwC,EAAE,EAAE,CACrE,UAAU,CAAC,GAAG,CAAC,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC;IAC5D,iBAAiB,CAAC;QAChB,IAAI,EAAE,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,CAAC;QAChE,IAAI,EAAE,IAAI,CAAC,IAAI;KAChB,CAAC;IACF,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAE3B;;;GAGG;AACH,MAAM,gBAAgB,GAAG,CAAC,MAAe,EAAW,EAAE;IACpD,IAAI,OAAO,GAAG,MAAM,CAAC;IAErB,OAAO,OAAO,EAAE,CAAC;QACf,MAAM,MAAM,GAAG,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;QACnE,MAAM,UAAU,GAAG,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;QACrD,MAAM,eAAe,GACnB,UAAU,KAAK,oBAAoB;YACnC,OAAO,CACL,gBAAO,CAAC,SAAS,CAAC;gBAChB,IAAI,EAAE,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;gBACpD,GAAG,EAAE,gBAAgB;aACtB,CAAC,CACH,CAAC;QAEJ,IACE,eAAe;YACf,UAAU,KAAK,uBAAuB;YACtC,iBAAiB,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,EAC5C,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,aAAa,GACjB,UAAU,KAAK,UAAU,IAAI,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,KAAK,OAAO,CAAC;QAC7F,OAAO,GAAG,aAAa,CAAC,CAAC,CAAC,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3F,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAa,gBAAgB;aACX,SAAI,GAAG,GAAG,+BAAsB,iBAAiB,CAAC;aAElD,gBAAW,GAAG,CAAC,CAAC;aAEhB,SAAI,GAAoB;QACtC,IAAI,EAAE;YACJ,IAAI,EAAE,YAAY;YAClB,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;YACzC,QAAQ,EAAE;gBACR,OAAO,EACL,wGAAwG;aAC3G;SACF;QACD,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE;YAClB,MAAM,GAAG,GACP,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,WAAW,CAAC;YAE7F,MAAM,UAAU,GAAG,CAAC,IAAe,EAAE,EAAE;gBACrC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;gBAC3B,MAAM,SAAS,GACb,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,KAAK,wBAAwB;oBAC9D,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;wBAC3E,cAAc,CAAC;gBAEnB,OAAO,SAAS,IAAI,iBAAiB,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1D,CAAC,CAAC;YAEF,MAAM,qBAAqB,GAAG,CAAC,IAA4C,EAAE,EAAE;gBAC7E,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;gBAEhC,MAAM,WAAW,GAAG,CAAC,KAAc,EAAE,EAAE;oBACrC,MAAM,GAAG,GAAG,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,YAAY,EAAE,CAAC,CAAC;oBAClE,MAAM,QAAQ,GAAG,gBAAO,CAAC,SAAS,CAAC;wBACjC,IAAI,EAAE,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,WAAW,EAAE,CAAC;wBAC1D,GAAG,EAAE,YAAY;qBAClB,CAAC,CAAC;oBAEH,OAAO,CACL,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;wBACtC,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CACjD,CAAC;gBACJ,CAAC,CAAC;gBAEF,OAAO,CACL,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,KAAK,kBAAkB;oBACxD,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,KAAK,aAAa;oBAClE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAC/B,CAAC;YACJ,CAAC,CAAC;YAEF,MAAM,gBAAgB,GAAG,CAAC,IAAe,EAAE,EAAE;gBAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;gBAC3B,MAAM,UAAU,GAAG,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;gBACrD,MAAM,WAAW,GACf,UAAU,KAAK,oBAAoB;oBACnC,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,KAAK,IAAI;oBACzD,OAAO,CACL,gBAAO,CAAC,SAAS,CAAC;wBAChB,IAAI,EAAE,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;wBACpD,GAAG,EAAE,gBAAgB;qBACtB,CAAC,CACH,CAAC;gBACJ,MAAM,WAAW,GAAG,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;gBACvE,MAAM,QAAQ,GACZ,UAAU,KAAK,UAAU;oBACzB,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,KAAK,IAAI;oBAC1D,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,KAAK,kBAAkB,CAAC;gBAEhE,OAAO,WAAW,IAAI,CAAC,QAAQ,IAAI,gBAAgB,CAAC,WAAW,CAAC,CAAC,CAAC;YACpE,CAAC,CAAC;YAEF,MAAM,KAAK,GAAG,CAAC,IAAe,EAAE,EAAE;gBAChC,MAAM,MAAM,GAAG,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;gBAE1D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;oBACnD,OAAO;gBACT,CAAC;gBAED,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,qBAAqB,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,IAAI,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC1F,OAAO;gBACT,CAAC;gBAED,OAAO,CAAC,MAAM,CAAC;oBACb,IAAI;oBACJ,SAAS,EAAE,SAAS;oBACpB,IAAI,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE;iBACzD,CAAC,CAAC;YACL,CAAC,CAAC;YAEF,OAAO;gBACL,CAAC,qBAAY,CAAC,oBAAoB,CAAC,EAAE,KAAK;gBAC1C,CAAC,qBAAY,CAAC,mBAAmB,CAAC,EAAE,KAAK;gBACzC,CAAC,qBAAY,CAAC,yBAAyB,CAAC,EAAE,KAAK;aAChD,CAAC;QACJ,CAAC;KACF,CAAC;IAEF,MAAM,CAAC,KAAK,CACV,OAKI,EAAE;QAEN,MAAM,EAAE,QAAQ,GAAG,OAAO,EAAE,GAAG,GAAG,gBAAgB,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC;QAExE,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IACzB,CAAC;;AA7GH,4CA8GC","sourcesContent":["import type { Linter, Rule } from 'eslint';\nimport type { TRuleSeverity } from '../rules/common';\nimport { AstNode, AstNodeTypes, HOUSE_PLUGIN_NAMESPACE } from './common';\n\nconst HOOK_NAME = /^use[A-Z]/;\nconst CALL_TYPES = new Set(['CallExpression', 'NewExpression']);\n\nconst isArrayContaining = (opts: { list: unknown; item: unknown }) =>\n Array.isArray(opts.list) && opts.list.includes(opts.item);\n\n/** `useX(...)`: a hook's callback is ours, so it counts. */\nconst isHookCall = (call: unknown) => {\n const callee = AstNode.readField({ node: call, key: 'callee' });\n const name = AstNode.readField({ node: callee, key: 'name' });\n\n return (\n AstNode.getType({ node: callee }) === 'Identifier' &&\n typeof name === 'string' &&\n HOOK_NAME.test(name)\n );\n};\n\n/** `node` is an argument of a call or `new` that is not a hook. */\nconst isLibraryArgument = (opts: { node: unknown; parent: unknown }) =>\n CALL_TYPES.has(AstNode.getType({ node: opts.parent }) ?? '') &&\n isArrayContaining({\n list: AstNode.readField({ node: opts.parent, key: 'arguments' }),\n item: opts.node,\n }) &&\n !isHookCall(opts.parent);\n\n/**\n * An object literal whose shape something else declares: a typed variable, `satisfies`, or an argument\n * of a non-hook call (a library option bag). A nested literal inherits it.\n */\nconst hasDeclaredShape = (object: unknown): boolean => {\n let current = object;\n\n while (current) {\n const parent = AstNode.readField({ node: current, key: 'parent' });\n const parentType = AstNode.getType({ node: parent });\n const isTypedVariable =\n parentType === 'VariableDeclarator' &&\n Boolean(\n AstNode.readField({\n node: AstNode.readField({ node: parent, key: 'id' }),\n key: 'typeAnnotation',\n }),\n );\n\n if (\n isTypedVariable ||\n parentType === 'TSSatisfiesExpression' ||\n isLibraryArgument({ node: current, parent })\n ) {\n return true;\n }\n\n const isNestedValue =\n parentType === 'Property' && AstNode.readField({ node: parent, key: 'value' }) === current;\n current = isNestedValue ? AstNode.readField({ node: parent, key: 'parent' }) : undefined;\n }\n\n return false;\n};\n\n/**\n * `venizia/max-params-own`. A function we write takes at most `max` positional parameters;\n * beyond that it takes one options object. A signature that belongs to someone else is not counted: an\n * inline callback handed to a call (map, reduce, sort, a library handler) or to a JSX prop, a function a\n * declared type fixes (`const x: TFn = (...)`, a member of a typed or `satisfies` object), and a\n * constructor whose every parameter is injected (`@inject`). A hook's callback (`useCallback(...)`) is ours.\n */\nexport class MaxParamsOwnRule {\n static readonly NAME = `${HOUSE_PLUGIN_NAMESPACE}/max-params-own`;\n\n static readonly DEFAULT_MAX = 5;\n\n static readonly RULE: Rule.RuleModule = {\n meta: {\n type: 'suggestion',\n schema: [{ type: 'integer', minimum: 0 }],\n messages: {\n tooMany:\n 'A function we write takes up to {{max}} positional parameters, not {{count}}: take one options object.',\n },\n },\n create: (context) => {\n const max =\n typeof context.options[0] === 'number' ? context.options[0] : MaxParamsOwnRule.DEFAULT_MAX;\n\n const isCallback = (node: Rule.Node) => {\n const parent = node.parent;\n const isJsxProp =\n AstNode.getType({ node: parent }) === 'JSXExpressionContainer' &&\n AstNode.getType({ node: AstNode.readField({ node: parent, key: 'parent' }) }) ===\n 'JSXAttribute';\n\n return isJsxProp || isLibraryArgument({ node, parent });\n };\n\n const isInjectedConstructor = (opts: { node: Rule.Node; params: unknown[] }) => {\n const parent = opts.node.parent;\n\n const isDecorated = (param: unknown) => {\n const own = AstNode.readField({ node: param, key: 'decorators' });\n const property = AstNode.readField({\n node: AstNode.readField({ node: param, key: 'parameter' }),\n key: 'decorators',\n });\n\n return (\n (Array.isArray(own) && own.length > 0) ||\n (Array.isArray(property) && property.length > 0)\n );\n };\n\n return (\n AstNode.getType({ node: parent }) === 'MethodDefinition' &&\n AstNode.readField({ node: parent, key: 'kind' }) === 'constructor' &&\n opts.params.every(isDecorated)\n );\n };\n\n const isTypedByContext = (node: Rule.Node) => {\n const parent = node.parent;\n const parentType = AstNode.getType({ node: parent });\n const isTypedInit =\n parentType === 'VariableDeclarator' &&\n AstNode.readField({ node: parent, key: 'init' }) === node &&\n Boolean(\n AstNode.readField({\n node: AstNode.readField({ node: parent, key: 'id' }),\n key: 'typeAnnotation',\n }),\n );\n const grandParent = AstNode.readField({ node: parent, key: 'parent' });\n const isMember =\n parentType === 'Property' &&\n AstNode.readField({ node: parent, key: 'value' }) === node &&\n AstNode.getType({ node: grandParent }) === 'ObjectExpression';\n\n return isTypedInit || (isMember && hasDeclaredShape(grandParent));\n };\n\n const check = (node: Rule.Node) => {\n const params = AstNode.readField({ node, key: 'params' });\n\n if (!Array.isArray(params) || params.length <= max) {\n return;\n }\n\n if (isCallback(node) || isInjectedConstructor({ node, params }) || isTypedByContext(node)) {\n return;\n }\n\n context.report({\n node,\n messageId: 'tooMany',\n data: { count: String(params.length), max: String(max) },\n });\n };\n\n return {\n [AstNodeTypes.FUNCTION_DECLARATION]: check,\n [AstNodeTypes.FUNCTION_EXPRESSION]: check,\n [AstNodeTypes.ARROW_FUNCTION_EXPRESSION]: check,\n };\n },\n };\n\n static build(\n opts: {\n /** @default 'error' */\n severity?: TRuleSeverity;\n /** @default 5 */\n max?: number;\n } = {},\n ): Linter.RuleEntry {\n const { severity = 'error', max = MaxParamsOwnRule.DEFAULT_MAX } = opts;\n\n return [severity, max];\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"max-params-own.rule.js","sourceRoot":"","sources":["../../../src/linters/house/max-params-own.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\nconst HOOK_NAME = /^use[A-Z]/;\nconst CALL_TYPES = new Set([AstNodeTypes.CALL_EXPRESSION, AstNodeTypes.NEW_EXPRESSION]);\n\nconst isArrayContaining = (opts: { list: unknown; item: unknown }) =>\n Array.isArray(opts.list) && opts.list.includes(opts.item);\n\n/** `useX(...)`: a hook's callback is ours, so it counts. */\nconst isHookCall = (call: unknown) => {\n const callee = AstNode.readField({ node: call, key: 'callee' });\n const name = AstNode.readField({ node: callee, key: 'name' });\n\n return (\n AstNode.getType({ node: callee }) === AstNodeTypes.IDENTIFIER &&\n typeof name === 'string' &&\n HOOK_NAME.test(name)\n );\n};\n\n/** `node` is an argument of a call or `new` that is not a hook. */\nconst isLibraryArgument = (opts: { node: unknown; parent: unknown }) =>\n CALL_TYPES.has(AstNode.getType({ node: opts.parent }) ?? '') &&\n isArrayContaining({\n list: AstNode.readField({ node: opts.parent, key: 'arguments' }),\n item: opts.node,\n }) &&\n !isHookCall(opts.parent);\n\n/**\n * An object literal whose shape something else declares: a typed variable, `satisfies`, or an argument\n * of a non-hook call (a library option bag). A nested literal inherits it.\n */\nconst hasDeclaredShape = (object: unknown): boolean => {\n let current = object;\n\n while (current) {\n const parent = AstNode.readField({ node: current, key: 'parent' });\n const parentType = AstNode.getType({ node: parent });\n const isTypedVariable =\n parentType === AstNodeTypes.VARIABLE_DECLARATOR &&\n Boolean(\n AstNode.readField({\n node: AstNode.readField({ node: parent, key: 'id' }),\n key: 'typeAnnotation',\n }),\n );\n\n if (\n isTypedVariable ||\n parentType === AstNodeTypes.SATISFIES_EXPRESSION ||\n isLibraryArgument({ node: current, parent })\n ) {\n return true;\n }\n\n const isNestedValue =\n parentType === AstNodeTypes.PROPERTY &&\n AstNode.readField({ node: parent, key: 'value' }) === current;\n current = isNestedValue ? AstNode.readField({ node: parent, key: 'parent' }) : undefined;\n }\n\n return false;\n};\n\n/**\n * `venizia/max-params-own`. A function we write takes at most `max` positional parameters;\n * beyond that it takes one options object. A signature that belongs to someone else is not counted: an\n * inline callback handed to a call (map, reduce, sort, a library handler) or to a JSX prop, a function a\n * declared type fixes (`const x: TFn = (...)`, a member of a typed or `satisfies` object), and a\n * constructor whose every parameter is injected (`@inject`). A hook's callback (`useCallback(...)`) is ours.\n */\nexport class MaxParamsOwnRule {\n static readonly NAME = `${HOUSE_PLUGIN_NAMESPACE}/max-params-own`;\n\n static readonly DEFAULT_MAX = 5;\n\n static readonly RULE: Rule.RuleModule = {\n meta: {\n type: 'suggestion',\n schema: [{ type: 'integer', minimum: 0 }],\n messages: {\n tooMany:\n 'A function we write takes up to {{max}} positional parameters, not {{count}}: take one options object.',\n },\n },\n create: (context) => {\n const max =\n typeof context.options[0] === 'number' ? context.options[0] : MaxParamsOwnRule.DEFAULT_MAX;\n\n const isCallback = (node: Rule.Node) => {\n const parent = node.parent;\n const isJsxProp =\n AstNode.getType({ node: parent }) === AstNodeTypes.JSX_EXPRESSION_CONTAINER &&\n AstNode.getType({ node: AstNode.readField({ node: parent, key: 'parent' }) }) ===\n AstNodeTypes.JSX_ATTRIBUTE;\n\n return isJsxProp || isLibraryArgument({ node, parent });\n };\n\n const isInjectedConstructor = (opts: { node: Rule.Node; params: unknown[] }) => {\n const parent = opts.node.parent;\n\n const isDecorated = (param: unknown) => {\n const own = AstNode.readField({ node: param, key: 'decorators' });\n const property = AstNode.readField({\n node: AstNode.readField({ node: param, key: 'parameter' }),\n key: 'decorators',\n });\n\n return (\n (Array.isArray(own) && own.length > 0) ||\n (Array.isArray(property) && property.length > 0)\n );\n };\n\n return (\n AstNode.getType({ node: parent }) === AstNodeTypes.METHOD_DEFINITION &&\n AstNode.readField({ node: parent, key: 'kind' }) === 'constructor' &&\n opts.params.every(isDecorated)\n );\n };\n\n const isTypedByContext = (node: Rule.Node) => {\n const parent = node.parent;\n const parentType = AstNode.getType({ node: parent });\n const isTypedInit =\n parentType === AstNodeTypes.VARIABLE_DECLARATOR &&\n AstNode.readField({ node: parent, key: 'init' }) === node &&\n Boolean(\n AstNode.readField({\n node: AstNode.readField({ node: parent, key: 'id' }),\n key: 'typeAnnotation',\n }),\n );\n const grandParent = AstNode.readField({ node: parent, key: 'parent' });\n const isMember =\n parentType === AstNodeTypes.PROPERTY &&\n AstNode.readField({ node: parent, key: 'value' }) === node &&\n AstNode.getType({ node: grandParent }) === AstNodeTypes.OBJECT_EXPRESSION;\n\n return isTypedInit || (isMember && hasDeclaredShape(grandParent));\n };\n\n const check = (node: Rule.Node) => {\n const params = AstNode.readField({ node, key: 'params' });\n\n if (!Array.isArray(params) || params.length <= max) {\n return;\n }\n\n if (isCallback(node) || isInjectedConstructor({ node, params }) || isTypedByContext(node)) {\n return;\n }\n\n context.report({\n node,\n messageId: 'tooMany',\n data: { count: String(params.length), max: String(max) },\n });\n };\n\n return {\n [AstNodeTypes.FUNCTION_DECLARATION]: check,\n [AstNodeTypes.FUNCTION_EXPRESSION]: check,\n [AstNodeTypes.ARROW_FUNCTION_EXPRESSION]: check,\n };\n },\n };\n\n static build(\n opts: {\n /** @default 'error' */\n severity?: TRuleSeverity;\n /** @default 5 */\n max?: number;\n } = {},\n ): Linter.RuleEntry {\n const { severity = 'error', max = MaxParamsOwnRule.DEFAULT_MAX } = opts;\n\n return [severity, max];\n }\n}\n"]}
|
|
@@ -5,10 +5,10 @@ const await_support_1 = require("./await-support");
|
|
|
5
5
|
const common_1 = require("./common");
|
|
6
6
|
/** Wrappers that carry no meaning of their own around the call or the instance: `(await new X().m()) as Y`, `new X()!.m()`, `new X()?.m()`. */
|
|
7
7
|
const TRANSPARENT_TYPES = new Set([
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
common_1.AstNodeTypes.CHAIN_EXPRESSION,
|
|
9
|
+
common_1.AstNodeTypes.AS_EXPRESSION,
|
|
10
|
+
common_1.AstNodeTypes.SATISFIES_EXPRESSION,
|
|
11
|
+
common_1.AstNodeTypes.NON_NULL_EXPRESSION,
|
|
12
12
|
]);
|
|
13
13
|
/** The classes whose `new` is awaited on its own account: `await new Promise(...)` calls no method, and `.then` on it is `no-await-promise-chain`'s. */
|
|
14
14
|
const EXEMPT_CLASSES = new Set(['Promise']);
|
|
@@ -48,7 +48,7 @@ class NoAwaitNewChainRule {
|
|
|
48
48
|
const callee = NoAwaitNewChainRule.unwrap({
|
|
49
49
|
node: common_1.AstNode.readField({ node: operand, key: 'callee' }),
|
|
50
50
|
});
|
|
51
|
-
if (common_1.AstNode.getType({ node: callee }) !==
|
|
51
|
+
if (common_1.AstNode.getType({ node: callee }) !== common_1.AstNodeTypes.MEMBER_EXPRESSION) {
|
|
52
52
|
return undefined;
|
|
53
53
|
}
|
|
54
54
|
const receiver = common_1.AstNode.readField({ node: callee, key: 'object' });
|
|
@@ -61,7 +61,7 @@ class NoAwaitNewChainRule {
|
|
|
61
61
|
node: common_1.AstNode.readField({ node: current, key: 'callee' }),
|
|
62
62
|
});
|
|
63
63
|
}
|
|
64
|
-
else if (type ===
|
|
64
|
+
else if (type === common_1.AstNodeTypes.MEMBER_EXPRESSION) {
|
|
65
65
|
current = NoAwaitNewChainRule.unwrap({
|
|
66
66
|
node: common_1.AstNode.readField({ node: current, key: 'object' }),
|
|
67
67
|
});
|
|
@@ -74,7 +74,7 @@ class NoAwaitNewChainRule {
|
|
|
74
74
|
return undefined;
|
|
75
75
|
}
|
|
76
76
|
const constructed = common_1.AstNode.readField({ node: current, key: 'callee' });
|
|
77
|
-
if (common_1.AstNode.getType({ node: constructed }) ===
|
|
77
|
+
if (common_1.AstNode.getType({ node: constructed }) === common_1.AstNodeTypes.IDENTIFIER &&
|
|
78
78
|
EXEMPT_CLASSES.has(String(common_1.AstNode.readField({ node: constructed, key: 'name' })))) {
|
|
79
79
|
return undefined;
|
|
80
80
|
}
|
|
@@ -88,10 +88,10 @@ class NoAwaitNewChainRule {
|
|
|
88
88
|
static isFirstToRun(opts) {
|
|
89
89
|
const { awaitNode, statement } = opts;
|
|
90
90
|
const type = common_1.AstNode.getType({ node: statement });
|
|
91
|
-
if (type ===
|
|
91
|
+
if (type === common_1.AstNodeTypes.EXPRESSION_STATEMENT) {
|
|
92
92
|
return common_1.AstNode.readField({ node: statement, key: 'expression' }) === awaitNode;
|
|
93
93
|
}
|
|
94
|
-
if (type !==
|
|
94
|
+
if (type !== common_1.AstNodeTypes.VARIABLE_DECLARATION) {
|
|
95
95
|
return false;
|
|
96
96
|
}
|
|
97
97
|
const declarations = common_1.AstNode.readField({ node: statement, key: 'declarations' });
|
|
@@ -103,18 +103,20 @@ class NoAwaitNewChainRule {
|
|
|
103
103
|
static nameOf(opts) {
|
|
104
104
|
let current = NoAwaitNewChainRule.unwrap({ node: opts.receiver });
|
|
105
105
|
while (common_1.AstNode.getType({ node: current }) === common_1.AstNodeTypes.CALL_EXPRESSION ||
|
|
106
|
-
common_1.AstNode.getType({ node: current }) ===
|
|
106
|
+
common_1.AstNode.getType({ node: current }) === common_1.AstNodeTypes.MEMBER_EXPRESSION) {
|
|
107
107
|
current = NoAwaitNewChainRule.unwrap({
|
|
108
108
|
node: common_1.AstNode.readField({
|
|
109
109
|
node: current,
|
|
110
|
-
key: common_1.AstNode.getType({ node: current }) ===
|
|
110
|
+
key: common_1.AstNode.getType({ node: current }) === common_1.AstNodeTypes.MEMBER_EXPRESSION
|
|
111
|
+
? 'object'
|
|
112
|
+
: 'callee',
|
|
111
113
|
}),
|
|
112
114
|
});
|
|
113
115
|
}
|
|
114
116
|
const constructed = common_1.AstNode.readField({ node: current, key: 'callee' });
|
|
115
|
-
const word = common_1.AstNode.getType({ node: constructed }) ===
|
|
117
|
+
const word = common_1.AstNode.getType({ node: constructed }) === common_1.AstNodeTypes.IDENTIFIER
|
|
116
118
|
? common_1.AstNode.readField({ node: constructed, key: 'name' })
|
|
117
|
-
: common_1.AstNode.getType({ node: constructed }) ===
|
|
119
|
+
: common_1.AstNode.getType({ node: constructed }) === common_1.AstNodeTypes.MEMBER_EXPRESSION
|
|
118
120
|
? common_1.AstNode.readField({
|
|
119
121
|
node: common_1.AstNode.readField({ node: constructed, key: 'property' }),
|
|
120
122
|
key: 'name',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-await-new-chain.rule.js","sourceRoot":"","sources":["../../../src/linters/house/no-await-new-chain.rule.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Rule } from 'eslint';\nimport type { TRuleSeverity } from '../rules/common';\nimport { AwaitSupport } from './await-support';\nimport { AstNode, AstNodeTypes, HOUSE_PLUGIN_NAMESPACE } from './common';\n\n/** Wrappers that carry no meaning of their own around the call or the instance: `(await new X().m()) as Y`, `new X()!.m()`, `new X()?.m()`. */\nconst TRANSPARENT_TYPES = new Set([\n 'ChainExpression',\n 'TSAsExpression',\n 'TSSatisfiesExpression',\n 'TSNonNullExpression',\n]);\n\n/** The classes whose `new` is awaited on its own account: `await new Promise(...)` calls no method, and `.then` on it is `no-await-promise-chain`'s. */\nconst EXEMPT_CLASSES = new Set(['Promise']);\n\n/**\n * `venizia/no-await-new-chain`. A method is never called on a fresh instance inside an `await`:\n * `await new Runner({ ... }).run(...)` and `const text = await new Response(body).text()` declare the instance first,\n * then await on its own line (`const runner = new Runner({ ... }); await runner.run(...);`). A builder chain\n * (`await new SignJWT(claims).setIssuer(iss).sign(key)`) declares the builder, then awaits its last call.\n *\n * `await new Promise(...)` calls no method and is allowed. `await new X().prop` is not a call and is allowed.\n *\n * The fix moves the instance, or the chain up to the last call, into a `const` in front of the statement. It is made\n * only when nothing that does more than read a value runs before the `await` inside the statement; otherwise the\n * finding is reported and left alone.\n */\nexport class NoAwaitNewChainRule {\n static readonly NAME = `${HOUSE_PLUGIN_NAMESPACE}/no-await-new-chain`;\n\n /** The expression under any transparent wrapper. */\n private static unwrap(opts: { node: unknown }): unknown {\n let current = opts.node;\n\n while (TRANSPARENT_TYPES.has(AstNode.getType({ node: current }) ?? '')) {\n current = AstNode.readField({ node: current, key: 'expression' });\n }\n\n return current;\n }\n\n /**\n * The receiver of the last call when the awaited value is a method call on a `new` (directly or through a chain of\n * calls and member reads), else `undefined`.\n */\n private static receiverOf(opts: { awaitNode: unknown }): Rule.Node | undefined {\n const operand = NoAwaitNewChainRule.unwrap({\n node: AstNode.readField({ node: opts.awaitNode, key: 'argument' }),\n });\n\n if (AstNode.getType({ node: operand }) !== AstNodeTypes.CALL_EXPRESSION) {\n return undefined;\n }\n\n const callee = NoAwaitNewChainRule.unwrap({\n node: AstNode.readField({ node: operand, key: 'callee' }),\n });\n\n if (AstNode.getType({ node: callee }) !== 'MemberExpression') {\n return undefined;\n }\n\n const receiver = AstNode.readField({ node: callee, key: 'object' });\n let current = NoAwaitNewChainRule.unwrap({ node: receiver });\n\n // Down the chain: `new X().a().b` is a call of a member of a call of a member of the `new`.\n for (;;) {\n const type = AstNode.getType({ node: current });\n\n if (type === AstNodeTypes.CALL_EXPRESSION) {\n current = NoAwaitNewChainRule.unwrap({\n node: AstNode.readField({ node: current, key: 'callee' }),\n });\n } else if (type === 'MemberExpression') {\n current = NoAwaitNewChainRule.unwrap({\n node: AstNode.readField({ node: current, key: 'object' }),\n });\n } else {\n break;\n }\n }\n\n if (AstNode.getType({ node: current }) !== AstNodeTypes.NEW_EXPRESSION) {\n return undefined;\n }\n\n const constructed = AstNode.readField({ node: current, key: 'callee' });\n\n if (\n AstNode.getType({ node: constructed }) === 'Identifier' &&\n EXEMPT_CLASSES.has(String(AstNode.readField({ node: constructed, key: 'name' })))\n ) {\n return undefined;\n }\n\n return AwaitSupport.isNode(receiver) ? receiver : undefined;\n }\n\n /**\n * Whether the `await` is the whole statement (`await f();`) or the whole initializer of a declaration with one\n * declarator (`const { a } = await f();`). Nothing runs before it there: a binding pattern and its defaults are\n * evaluated after the initializer.\n */\n private static isFirstToRun(opts: { awaitNode: unknown; statement: unknown }): boolean {\n const { awaitNode, statement } = opts;\n const type = AstNode.getType({ node: statement });\n\n if (type === 'ExpressionStatement') {\n return AstNode.readField({ node: statement, key: 'expression' }) === awaitNode;\n }\n\n if (type !== 'VariableDeclaration') {\n return false;\n }\n\n const declarations = AstNode.readField({ node: statement, key: 'declarations' });\n\n return (\n Array.isArray(declarations) &&\n declarations.length === 1 &&\n AstNode.readField({ node: declarations[0], key: 'init' }) === awaitNode\n );\n }\n\n /** `Response` becomes `response`, `ns.SignJWT` becomes `signJWT`; anything else is `instance`. */\n private static nameOf(opts: { receiver: unknown }): string {\n let current = NoAwaitNewChainRule.unwrap({ node: opts.receiver });\n\n while (\n AstNode.getType({ node: current }) === AstNodeTypes.CALL_EXPRESSION ||\n AstNode.getType({ node: current }) === 'MemberExpression'\n ) {\n current = NoAwaitNewChainRule.unwrap({\n node: AstNode.readField({\n node: current,\n key: AstNode.getType({ node: current }) === 'MemberExpression' ? 'object' : 'callee',\n }),\n });\n }\n\n const constructed = AstNode.readField({ node: current, key: 'callee' });\n const word =\n AstNode.getType({ node: constructed }) === 'Identifier'\n ? AstNode.readField({ node: constructed, key: 'name' })\n : AstNode.getType({ node: constructed }) === 'MemberExpression'\n ? AstNode.readField({\n node: AstNode.readField({ node: constructed, key: 'property' }),\n key: 'name',\n })\n : undefined;\n\n return typeof word === 'string' && /^[A-Za-z_$][\\w$]*$/.test(word)\n ? `${word[0]?.toLowerCase()}${word.slice(1)}`\n : 'instance';\n }\n\n static readonly RULE: Rule.RuleModule = {\n meta: {\n type: 'suggestion',\n fixable: 'code',\n schema: [],\n messages: {\n chain:\n 'Do not call a method on a new instance inside an `await`: declare the instance first (`const runner = new Runner(options);`), then `await runner.run();` on its own line.',\n },\n },\n create: (context) => {\n const { sourceCode } = context;\n\n return {\n [AstNodeTypes.AWAIT_EXPRESSION]: (node: Rule.Node) => {\n const receiver = NoAwaitNewChainRule.receiverOf({ awaitNode: node });\n\n if (receiver === undefined) {\n return;\n }\n\n const statement = AwaitSupport.hoistTarget({ awaitNode: node });\n const range = AwaitSupport.rangeOf({ node: receiver });\n const canFix =\n statement !== undefined &&\n range !== undefined &&\n (NoAwaitNewChainRule.isFirstToRun({ awaitNode: node, statement }) ||\n !AwaitSupport.hasEffectBefore({ statement, awaitNode: node, sourceCode }));\n\n context.report({\n node,\n messageId: 'chain',\n fix:\n canFix && range !== undefined\n ? (fixer) => {\n const name = AwaitSupport.freshName({\n node,\n base: NoAwaitNewChainRule.nameOf({ receiver }),\n sourceCode,\n });\n const indent = AwaitSupport.indentOf({ node: statement, sourceCode });\n\n return [\n fixer.insertTextBefore(\n statement,\n `const ${name} = ${sourceCode.getText(receiver)};\\n${indent}`,\n ),\n fixer.replaceTextRange(range, name),\n ];\n }\n : null,\n });\n },\n };\n },\n };\n\n static build(opts: { severity?: TRuleSeverity } = {}): TRuleSeverity {\n return opts.severity ?? 'error';\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"no-await-new-chain.rule.js","sourceRoot":"","sources":["../../../src/linters/house/no-await-new-chain.rule.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Rule } from 'eslint';\nimport type { TRuleSeverity } from '../rules/common';\nimport { AwaitSupport } from './await-support';\nimport { AstNode, AstNodeTypes, HOUSE_PLUGIN_NAMESPACE } from './common';\n\n/** Wrappers that carry no meaning of their own around the call or the instance: `(await new X().m()) as Y`, `new X()!.m()`, `new X()?.m()`. */\nconst TRANSPARENT_TYPES = new Set([\n AstNodeTypes.CHAIN_EXPRESSION,\n AstNodeTypes.AS_EXPRESSION,\n AstNodeTypes.SATISFIES_EXPRESSION,\n AstNodeTypes.NON_NULL_EXPRESSION,\n]);\n\n/** The classes whose `new` is awaited on its own account: `await new Promise(...)` calls no method, and `.then` on it is `no-await-promise-chain`'s. */\nconst EXEMPT_CLASSES = new Set(['Promise']);\n\n/**\n * `venizia/no-await-new-chain`. A method is never called on a fresh instance inside an `await`:\n * `await new Runner({ ... }).run(...)` and `const text = await new Response(body).text()` declare the instance first,\n * then await on its own line (`const runner = new Runner({ ... }); await runner.run(...);`). A builder chain\n * (`await new SignJWT(claims).setIssuer(iss).sign(key)`) declares the builder, then awaits its last call.\n *\n * `await new Promise(...)` calls no method and is allowed. `await new X().prop` is not a call and is allowed.\n *\n * The fix moves the instance, or the chain up to the last call, into a `const` in front of the statement. It is made\n * only when nothing that does more than read a value runs before the `await` inside the statement; otherwise the\n * finding is reported and left alone.\n */\nexport class NoAwaitNewChainRule {\n static readonly NAME = `${HOUSE_PLUGIN_NAMESPACE}/no-await-new-chain`;\n\n /** The expression under any transparent wrapper. */\n private static unwrap(opts: { node: unknown }): unknown {\n let current = opts.node;\n\n while (TRANSPARENT_TYPES.has(AstNode.getType({ node: current }) ?? '')) {\n current = AstNode.readField({ node: current, key: 'expression' });\n }\n\n return current;\n }\n\n /**\n * The receiver of the last call when the awaited value is a method call on a `new` (directly or through a chain of\n * calls and member reads), else `undefined`.\n */\n private static receiverOf(opts: { awaitNode: unknown }): Rule.Node | undefined {\n const operand = NoAwaitNewChainRule.unwrap({\n node: AstNode.readField({ node: opts.awaitNode, key: 'argument' }),\n });\n\n if (AstNode.getType({ node: operand }) !== AstNodeTypes.CALL_EXPRESSION) {\n return undefined;\n }\n\n const callee = NoAwaitNewChainRule.unwrap({\n node: AstNode.readField({ node: operand, key: 'callee' }),\n });\n\n if (AstNode.getType({ node: callee }) !== AstNodeTypes.MEMBER_EXPRESSION) {\n return undefined;\n }\n\n const receiver = AstNode.readField({ node: callee, key: 'object' });\n let current = NoAwaitNewChainRule.unwrap({ node: receiver });\n\n // Down the chain: `new X().a().b` is a call of a member of a call of a member of the `new`.\n for (;;) {\n const type = AstNode.getType({ node: current });\n\n if (type === AstNodeTypes.CALL_EXPRESSION) {\n current = NoAwaitNewChainRule.unwrap({\n node: AstNode.readField({ node: current, key: 'callee' }),\n });\n } else if (type === AstNodeTypes.MEMBER_EXPRESSION) {\n current = NoAwaitNewChainRule.unwrap({\n node: AstNode.readField({ node: current, key: 'object' }),\n });\n } else {\n break;\n }\n }\n\n if (AstNode.getType({ node: current }) !== AstNodeTypes.NEW_EXPRESSION) {\n return undefined;\n }\n\n const constructed = AstNode.readField({ node: current, key: 'callee' });\n\n if (\n AstNode.getType({ node: constructed }) === AstNodeTypes.IDENTIFIER &&\n EXEMPT_CLASSES.has(String(AstNode.readField({ node: constructed, key: 'name' })))\n ) {\n return undefined;\n }\n\n return AwaitSupport.isNode(receiver) ? receiver : undefined;\n }\n\n /**\n * Whether the `await` is the whole statement (`await f();`) or the whole initializer of a declaration with one\n * declarator (`const { a } = await f();`). Nothing runs before it there: a binding pattern and its defaults are\n * evaluated after the initializer.\n */\n private static isFirstToRun(opts: { awaitNode: unknown; statement: unknown }): boolean {\n const { awaitNode, statement } = opts;\n const type = AstNode.getType({ node: statement });\n\n if (type === AstNodeTypes.EXPRESSION_STATEMENT) {\n return AstNode.readField({ node: statement, key: 'expression' }) === awaitNode;\n }\n\n if (type !== AstNodeTypes.VARIABLE_DECLARATION) {\n return false;\n }\n\n const declarations = AstNode.readField({ node: statement, key: 'declarations' });\n\n return (\n Array.isArray(declarations) &&\n declarations.length === 1 &&\n AstNode.readField({ node: declarations[0], key: 'init' }) === awaitNode\n );\n }\n\n /** `Response` becomes `response`, `ns.SignJWT` becomes `signJWT`; anything else is `instance`. */\n private static nameOf(opts: { receiver: unknown }): string {\n let current = NoAwaitNewChainRule.unwrap({ node: opts.receiver });\n\n while (\n AstNode.getType({ node: current }) === AstNodeTypes.CALL_EXPRESSION ||\n AstNode.getType({ node: current }) === AstNodeTypes.MEMBER_EXPRESSION\n ) {\n current = NoAwaitNewChainRule.unwrap({\n node: AstNode.readField({\n node: current,\n key:\n AstNode.getType({ node: current }) === AstNodeTypes.MEMBER_EXPRESSION\n ? 'object'\n : 'callee',\n }),\n });\n }\n\n const constructed = AstNode.readField({ node: current, key: 'callee' });\n const word =\n AstNode.getType({ node: constructed }) === AstNodeTypes.IDENTIFIER\n ? AstNode.readField({ node: constructed, key: 'name' })\n : AstNode.getType({ node: constructed }) === AstNodeTypes.MEMBER_EXPRESSION\n ? AstNode.readField({\n node: AstNode.readField({ node: constructed, key: 'property' }),\n key: 'name',\n })\n : undefined;\n\n return typeof word === 'string' && /^[A-Za-z_$][\\w$]*$/.test(word)\n ? `${word[0]?.toLowerCase()}${word.slice(1)}`\n : 'instance';\n }\n\n static readonly RULE: Rule.RuleModule = {\n meta: {\n type: 'suggestion',\n fixable: 'code',\n schema: [],\n messages: {\n chain:\n 'Do not call a method on a new instance inside an `await`: declare the instance first (`const runner = new Runner(options);`), then `await runner.run();` on its own line.',\n },\n },\n create: (context) => {\n const { sourceCode } = context;\n\n return {\n [AstNodeTypes.AWAIT_EXPRESSION]: (node: Rule.Node) => {\n const receiver = NoAwaitNewChainRule.receiverOf({ awaitNode: node });\n\n if (receiver === undefined) {\n return;\n }\n\n const statement = AwaitSupport.hoistTarget({ awaitNode: node });\n const range = AwaitSupport.rangeOf({ node: receiver });\n const canFix =\n statement !== undefined &&\n range !== undefined &&\n (NoAwaitNewChainRule.isFirstToRun({ awaitNode: node, statement }) ||\n !AwaitSupport.hasEffectBefore({ statement, awaitNode: node, sourceCode }));\n\n context.report({\n node,\n messageId: 'chain',\n fix:\n canFix && range !== undefined\n ? (fixer) => {\n const name = AwaitSupport.freshName({\n node,\n base: NoAwaitNewChainRule.nameOf({ receiver }),\n sourceCode,\n });\n const indent = AwaitSupport.indentOf({ node: statement, sourceCode });\n\n return [\n fixer.insertTextBefore(\n statement,\n `const ${name} = ${sourceCode.getText(receiver)};\\n${indent}`,\n ),\n fixer.replaceTextRange(range, name),\n ];\n }\n : null,\n });\n },\n };\n },\n };\n\n static build(opts: { severity?: TRuleSeverity } = {}): TRuleSeverity {\n return opts.severity ?? 'error';\n }\n}\n"]}
|
|
@@ -12,40 +12,41 @@ const collectValue = (opts) => {
|
|
|
12
12
|
const type = common_1.AstNode.getType({ node }) ?? '';
|
|
13
13
|
const value = (child) => collectValue({ node: child, parameter, identifiers });
|
|
14
14
|
switch (type) {
|
|
15
|
-
case
|
|
15
|
+
case common_1.AstNodeTypes.LITERAL: {
|
|
16
16
|
return true;
|
|
17
17
|
}
|
|
18
|
-
case
|
|
18
|
+
case common_1.AstNodeTypes.IDENTIFIER: {
|
|
19
19
|
identifiers.push(node);
|
|
20
20
|
return true;
|
|
21
21
|
}
|
|
22
|
-
case
|
|
22
|
+
case common_1.AstNodeTypes.TEMPLATE_LITERAL: {
|
|
23
23
|
return promise_chain_support_1.PromiseChainSupport.isConstant({ node });
|
|
24
24
|
}
|
|
25
|
-
case
|
|
25
|
+
case common_1.AstNodeTypes.UNARY_EXPRESSION: {
|
|
26
26
|
return promise_chain_support_1.PromiseChainSupport.isConstant({ node });
|
|
27
27
|
}
|
|
28
|
-
case
|
|
28
|
+
case common_1.AstNodeTypes.CHAIN_EXPRESSION: {
|
|
29
29
|
return value(common_1.AstNode.readField({ node, key: 'expression' }));
|
|
30
30
|
}
|
|
31
|
-
case
|
|
31
|
+
case common_1.AstNodeTypes.MEMBER_EXPRESSION: {
|
|
32
32
|
// Only a read of the error itself: `error.message`, `error?.response.status`.
|
|
33
33
|
const object = common_1.AstNode.readField({ node, key: 'object' });
|
|
34
34
|
const isRead = common_1.AstNode.readField({ node, key: 'computed' }) !== true ||
|
|
35
|
-
common_1.AstNode.getType({ node: common_1.AstNode.readField({ node, key: 'property' }) }) ===
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
common_1.AstNode.getType({ node: common_1.AstNode.readField({ node, key: 'property' }) }) ===
|
|
36
|
+
common_1.AstNodeTypes.LITERAL;
|
|
37
|
+
const isRooted = common_1.AstNode.getType({ node: object }) === common_1.AstNodeTypes.MEMBER_EXPRESSION ||
|
|
38
|
+
(common_1.AstNode.getType({ node: object }) === common_1.AstNodeTypes.IDENTIFIER &&
|
|
38
39
|
common_1.AstNode.readField({ node: object, key: 'name' }) === parameter);
|
|
39
40
|
return isRead && isRooted && parameter !== undefined && value(object);
|
|
40
41
|
}
|
|
41
|
-
case
|
|
42
|
+
case common_1.AstNodeTypes.ARRAY_EXPRESSION: {
|
|
42
43
|
const elements = common_1.AstNode.readField({ node, key: 'elements' });
|
|
43
44
|
return (Array.isArray(elements) && elements.every((element) => element === null || value(element)));
|
|
44
45
|
}
|
|
45
|
-
case
|
|
46
|
+
case common_1.AstNodeTypes.OBJECT_EXPRESSION: {
|
|
46
47
|
const properties = common_1.AstNode.readField({ node, key: 'properties' });
|
|
47
48
|
return (Array.isArray(properties) &&
|
|
48
|
-
properties.every((property) => common_1.AstNode.getType({ node: property }) ===
|
|
49
|
+
properties.every((property) => common_1.AstNode.getType({ node: property }) === common_1.AstNodeTypes.PROPERTY &&
|
|
49
50
|
common_1.AstNode.readField({ node: property, key: 'computed' }) !== true &&
|
|
50
51
|
common_1.AstNode.readField({ node: property, key: 'method' }) !== true &&
|
|
51
52
|
common_1.AstNode.readField({ node: property, key: 'kind' }) === 'init' &&
|
|
@@ -78,9 +79,9 @@ const planFix = (opts) => {
|
|
|
78
79
|
const call = common_1.AstNode.readField({ node: awaitNode, key: 'argument' });
|
|
79
80
|
const callee = common_1.AstNode.readField({ node: call, key: 'callee' });
|
|
80
81
|
const args = common_1.AstNode.readField({ node: call, key: 'arguments' });
|
|
81
|
-
if (common_1.AstNode.getType({ node: call }) !==
|
|
82
|
+
if (common_1.AstNode.getType({ node: call }) !== common_1.AstNodeTypes.CALL_EXPRESSION ||
|
|
82
83
|
common_1.AstNode.readField({ node: call, key: 'optional' }) === true ||
|
|
83
|
-
common_1.AstNode.getType({ node: callee }) !==
|
|
84
|
+
common_1.AstNode.getType({ node: callee }) !== common_1.AstNodeTypes.MEMBER_EXPRESSION ||
|
|
84
85
|
common_1.AstNode.readField({ node: callee, key: 'computed' }) === true ||
|
|
85
86
|
common_1.AstNode.readField({ node: callee, key: 'optional' }) === true ||
|
|
86
87
|
promise_chain_support_1.PromiseChainSupport.memberName({ member: callee }) !== 'catch' ||
|
|
@@ -92,7 +93,7 @@ const planFix = (opts) => {
|
|
|
92
93
|
const params = common_1.AstNode.readField({ node: handler, key: 'params' });
|
|
93
94
|
const body = common_1.AstNode.readField({ node: handler, key: 'body' });
|
|
94
95
|
const parameter = Array.isArray(params) ? params[0] : undefined;
|
|
95
|
-
if (common_1.AstNode.getType({ node: handler }) !==
|
|
96
|
+
if (common_1.AstNode.getType({ node: handler }) !== common_1.AstNodeTypes.ARROW_FUNCTION_EXPRESSION ||
|
|
96
97
|
common_1.AstNode.readField({ node: handler, key: 'async' }) === true ||
|
|
97
98
|
common_1.AstNode.getType({ node: body }) === common_1.AstNodeTypes.BLOCK_STATEMENT ||
|
|
98
99
|
common_1.AstNode.readField({ node: handler, key: 'returnType' }) ||
|
|
@@ -100,7 +101,7 @@ const planFix = (opts) => {
|
|
|
100
101
|
!Array.isArray(params) ||
|
|
101
102
|
params.length > 1 ||
|
|
102
103
|
(parameter !== undefined &&
|
|
103
|
-
(common_1.AstNode.getType({ node: parameter }) !==
|
|
104
|
+
(common_1.AstNode.getType({ node: parameter }) !== common_1.AstNodeTypes.IDENTIFIER ||
|
|
104
105
|
common_1.AstNode.readField({ node: parameter, key: 'typeAnnotation' }) ||
|
|
105
106
|
common_1.AstNode.readField({ node: parameter, key: 'optional' }) === true))) {
|
|
106
107
|
return undefined;
|
|
@@ -118,10 +119,10 @@ const planFix = (opts) => {
|
|
|
118
119
|
const id = common_1.AstNode.readField({ node: declarator, key: 'id' });
|
|
119
120
|
const declarations = common_1.AstNode.readField({ node: declaration, key: 'declarations' });
|
|
120
121
|
const kind = String(common_1.AstNode.readField({ node: declaration, key: 'kind' }));
|
|
121
|
-
if (common_1.AstNode.getType({ node: declarator }) !==
|
|
122
|
+
if (common_1.AstNode.getType({ node: declarator }) !== common_1.AstNodeTypes.VARIABLE_DECLARATOR ||
|
|
122
123
|
common_1.AstNode.readField({ node: declarator, key: 'init' }) !== awaitNode ||
|
|
123
124
|
common_1.AstNode.readField({ node: declarator, key: 'definite' }) === true ||
|
|
124
|
-
common_1.AstNode.getType({ node: id }) !==
|
|
125
|
+
common_1.AstNode.getType({ node: id }) !== common_1.AstNodeTypes.IDENTIFIER ||
|
|
125
126
|
!await_support_1.AwaitSupport.isNode(declarator) ||
|
|
126
127
|
!await_support_1.AwaitSupport.isNode(declaration) ||
|
|
127
128
|
!Array.isArray(declarations) ||
|
|
@@ -149,8 +150,8 @@ const planFix = (opts) => {
|
|
|
149
150
|
if (reference.isWrite() ||
|
|
150
151
|
(annotation === '' &&
|
|
151
152
|
(reference.from.variableScope !== variable.scope.variableScope ||
|
|
152
|
-
parentType ===
|
|
153
|
-
parentType ===
|
|
153
|
+
parentType === common_1.AstNodeTypes.EXPORT_SPECIFIER ||
|
|
154
|
+
parentType === common_1.AstNodeTypes.TYPE_QUERY))) {
|
|
154
155
|
return undefined;
|
|
155
156
|
}
|
|
156
157
|
}
|
|
@@ -164,7 +165,7 @@ const planFix = (opts) => {
|
|
|
164
165
|
// `x = []` on a `let x;` with no annotation makes an evolving `any[]`, looser than the `never[]` it was.
|
|
165
166
|
const elements = common_1.AstNode.readField({ node: body, key: 'elements' });
|
|
166
167
|
if (annotation === '' &&
|
|
167
|
-
common_1.AstNode.getType({ node: body }) ===
|
|
168
|
+
common_1.AstNode.getType({ node: body }) === common_1.AstNodeTypes.ARRAY_EXPRESSION &&
|
|
168
169
|
Array.isArray(elements) &&
|
|
169
170
|
elements.length === 0) {
|
|
170
171
|
return undefined;
|
|
@@ -201,7 +202,7 @@ const planFix = (opts) => {
|
|
|
201
202
|
.filter(await_support_1.AwaitSupport.isNode)
|
|
202
203
|
.map((identifier) => {
|
|
203
204
|
const parent = await_support_1.AwaitSupport.parentOf({ node: identifier });
|
|
204
|
-
const isShorthand = common_1.AstNode.getType({ node: parent }) ===
|
|
205
|
+
const isShorthand = common_1.AstNode.getType({ node: parent }) === common_1.AstNodeTypes.PROPERTY &&
|
|
205
206
|
common_1.AstNode.readField({ node: parent, key: 'shorthand' }) === true;
|
|
206
207
|
return {
|
|
207
208
|
range: identifier.range ?? [0, 0],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-await-promise-chain.rule.js","sourceRoot":"","sources":["../../../src/linters/house/no-await-promise-chain.rule.ts"],"names":[],"mappings":";;;AAEA,mDAAgE;AAChE,qCAAyE;AACzE,mEAA8D;AAE9D,2EAA2E;AAC3E,MAAM,UAAU,GAAG,OAAO,CAAC;AAc3B,wGAAwG;AACxG,MAAM,YAAY,GAAG,CAAC,IAIrB,EAAW,EAAE;IACZ,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC;IAC9C,MAAM,IAAI,GAAG,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;IAC7C,MAAM,KAAK,GAAG,CAAC,KAAc,EAAE,EAAE,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC,CAAC;IAExF,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,SAAS,CAAC,CAAC,CAAC;YACf,OAAO,IAAI,CAAC;QACd,CAAC;QACD,KAAK,YAAY,CAAC,CAAC,CAAC;YAClB,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAEvB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,KAAK,iBAAiB,CAAC,CAAC,CAAC;YACvB,OAAO,2CAAmB,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QAClD,CAAC;QACD,KAAK,iBAAiB,CAAC,CAAC,CAAC;YACvB,OAAO,2CAAmB,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QAClD,CAAC;QACD,KAAK,iBAAiB,CAAC,CAAC,CAAC;YACvB,OAAO,KAAK,CAAC,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC;QAC/D,CAAC;QACD,KAAK,kBAAkB,CAAC,CAAC,CAAC;YACxB,8EAA8E;YAC9E,MAAM,MAAM,GAAG,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;YAC1D,MAAM,MAAM,GACV,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,KAAK,IAAI;gBACrD,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,KAAK,SAAS,CAAC;YACxF,MAAM,QAAQ,GACZ,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,KAAK,kBAAkB;gBACxD,CAAC,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,KAAK,YAAY;oBACjD,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,KAAK,SAAS,CAAC,CAAC;YAEpE,OAAO,MAAM,IAAI,QAAQ,IAAI,SAAS,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC;QACxE,CAAC;QACD,KAAK,iBAAiB,CAAC,CAAC,CAAC;YACvB,MAAM,QAAQ,GAAG,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,CAAC;YAE9D,OAAO,CACL,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAC3F,CAAC;QACJ,CAAC;QACD,KAAK,kBAAkB,CAAC,CAAC,CAAC;YACxB,MAAM,UAAU,GAAG,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,YAAY,EAAE,CAAC,CAAC;YAElE,OAAO,CACL,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC;gBACzB,UAAU,CAAC,KAAK,CACd,CAAC,QAAQ,EAAE,EAAE,CACX,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,KAAK,UAAU;oBAClD,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,KAAK,IAAI;oBAC/D,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,KAAK,IAAI;oBAC7D,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,KAAK,MAAM;oBAC7D,KAAK,CAAC,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC,CAC7D,CACF,CAAC;QACJ,CAAC;QACD,OAAO,CAAC,CAAC,CAAC;YACR,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;AACH,CAAC,CAAC;AAEF,mHAAmH;AACnH,MAAM,gBAAgB,GAAG,CAAC,IAAiD,EAAW,EAAE;IACtF,KAAK,IAAI,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC;QACxD,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7B,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,OAAO,GAAG,CAAC,IAAsD,EAAwB,EAAE;IAC/F,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC;IACvC,MAAM,IAAI,GAAG,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,CAAC;IACrE,MAAM,MAAM,GAAG,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;IAChE,MAAM,IAAI,GAAG,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,WAAW,EAAE,CAAC,CAAC;IAEjE,IACE,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,KAAK,gBAAgB;QACpD,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,KAAK,IAAI;QAC3D,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,KAAK,kBAAkB;QACxD,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,KAAK,IAAI;QAC7D,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,KAAK,IAAI;QAC7D,2CAAmB,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,KAAK,OAAO;QAC9D,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;QACpB,IAAI,CAAC,MAAM,KAAK,CAAC,EACjB,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,OAAO,GAAY,IAAI,CAAC,CAAC,CAAC,CAAC;IACjC,MAAM,MAAM,GAAG,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;IACnE,MAAM,IAAI,GAAG,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC;IAC/D,MAAM,SAAS,GAAY,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAEzE,IACE,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,KAAK,yBAAyB;QAChE,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,KAAK,IAAI;QAC3D,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,KAAK,qBAAY,CAAC,eAAe;QAChE,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,YAAY,EAAE,CAAC;QACvD,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,gBAAgB,EAAE,CAAC;QAC3D,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QACtB,MAAM,CAAC,MAAM,GAAG,CAAC;QACjB,CAAC,SAAS,KAAK,SAAS;YACtB,CAAC,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,KAAK,YAAY;gBACpD,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,gBAAgB,EAAE,CAAC;gBAC7D,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,KAAK,IAAI,CAAC,CAAC,EACtE,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,QAAQ,GAAG,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;IAEpE,IACE,CAAC,4BAAY,CAAC,MAAM,CAAC,QAAQ,CAAC;QAC9B,CAAC,4BAAY,CAAC,MAAM,CAAC,IAAI,CAAC;QAC1B,CAAC,4BAAY,CAAC,MAAM,CAAC,OAAO,CAAC;QAC7B,2CAAmB,CAAC,eAAe,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;QACvD,mBAAmB,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,EACtD,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,UAAU,GAAG,4BAAY,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;IAC9D,MAAM,WAAW,GAAG,4BAAY,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;IAChE,MAAM,EAAE,GAAG,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9D,MAAM,YAAY,GAAG,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,cAAc,EAAE,CAAC,CAAC;IACnF,MAAM,IAAI,GAAG,MAAM,CAAC,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;IAE3E,IACE,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,KAAK,oBAAoB;QAC9D,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,KAAK,SAAS;QAClE,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,KAAK,IAAI;QACjE,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,KAAK,YAAY;QAC9C,CAAC,4BAAY,CAAC,MAAM,CAAC,UAAU,CAAC;QAChC,CAAC,4BAAY,CAAC,MAAM,CAAC,WAAW,CAAC;QACjC,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC;QAC5B,YAAY,CAAC,MAAM,KAAK,CAAC;QACzB,CAAC,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;QAChC,CAAC,+BAAe,CAAC,GAAG,CAClB,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,4BAAY,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,CAC9E,EACD,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,CAAC,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;IAClE,MAAM,cAAc,GAAG,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,gBAAgB,EAAE,CAAC,CAAC;IAC9E,MAAM,UAAU,GAAG,4BAAY,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAEjG,4GAA4G;IAC5G,8GAA8G;IAC9G,MAAM,QAAQ,GAAG,UAAU,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IAElG,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,KAAK,MAAM,SAAS,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;QAC5C,IAAI,SAAS,CAAC,UAAU,KAAK,EAAE,EAAE,CAAC;YAChC,SAAS;QACX,CAAC;QAED,MAAM,UAAU,GAAG,gBAAO,CAAC,OAAO,CAAC;YACjC,IAAI,EAAE,4BAAY,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC,UAAU,EAAE,CAAC;SAC5D,CAAC,CAAC;QAEH,IACE,SAAS,CAAC,OAAO,EAAE;YACnB,CAAC,UAAU,KAAK,EAAE;gBAChB,CAAC,SAAS,CAAC,IAAI,CAAC,aAAa,KAAK,QAAQ,CAAC,KAAK,CAAC,aAAa;oBAC5D,UAAU,KAAK,iBAAiB;oBAChC,UAAU,KAAK,aAAa,CAAC,CAAC,EAClC,CAAC;YACD,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;IAED,MAAM,aAAa,GACjB,SAAS,KAAK,SAAS;QACrB,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,MAAM,CAAC,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;IAClE,MAAM,WAAW,GAAc,EAAE,CAAC;IAElC,IAAI,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,aAAa,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;QACzE,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,yGAAyG;IACzG,MAAM,QAAQ,GAAG,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,CAAC;IAEpE,IACE,UAAU,KAAK,EAAE;QACjB,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,KAAK,iBAAiB;QACrD,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;QACvB,QAAQ,CAAC,MAAM,KAAK,CAAC,EACrB,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,iBAAiB,GAAG,UAAU;SACjC,oBAAoB,CAAC,OAAO,CAAC;SAC7B,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,aAAa,CAAC,CAAC;IACjD,MAAM,UAAU,GAAG,IAAI,GAAG,CACxB,iBAAiB,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,EAAE,CAC7E,CAAC;IACF,MAAM,SAAS,GAAG,IAAI,GAAG,CACvB,WAAW;SACR,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;SACnD,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,MAAM,CAAC,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CACrF,CAAC;IAEF,qGAAqG;IACrG,IAAI,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QACxB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,KAAK,GAAG,UAAU,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,CAAC,SAAiB,EAAE,EAAE,CACpC,SAAS,KAAK,IAAI;QAClB,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC;QACxB,CAAC,SAAS,KAAK,aAAa,IAAI,gBAAgB,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;IAChF,MAAM,IAAI,GAAG,aAAa,IAAI,UAAU,CAAC;IACzC,IAAI,SAAS,GAAG,IAAI,CAAC;IAErB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACnD,SAAS,GAAG,GAAG,IAAI,GAAG,KAAK,EAAE,CAAC;IAChC,CAAC;IAED,MAAM,QAAQ,GAAG,UAAU,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAC3D,MAAM,QAAQ,GAAG,CAAC,KAAmC,EAAE,KAAmC,EAAE,EAAE,CAC5F,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC;IAE7F,IACE,QAAQ,CAAC,IAAI,CACX,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,CAC9F,EACD,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACvC,IAAI,SAAS,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzC,IAAI,SAAS,KAAK,aAAa,IAAI,UAAU,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QACvD,MAAM,KAAK,GAAG,CAAC,GAAG,UAAU,CAAC;aAC1B,MAAM,CAAC,4BAAY,CAAC,MAAM,CAAC;aAC3B,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE;YAClB,MAAM,MAAM,GAAG,4BAAY,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;YAC3D,MAAM,WAAW,GACf,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,KAAK,UAAU;gBAChD,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,CAAC,KAAK,IAAI,CAAC;YAEjE,OAAO;gBACL,KAAK,EAAE,UAAU,CAAC,KAAK,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC;gBACjC,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,aAAa,KAAK,SAAS,EAAE,CAAC,CAAC,CAAC,SAAS;aACjE,CAAC;QACJ,CAAC,CAAC;aACD,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAEzD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,SAAS;gBACP,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;oBAC7C,IAAI,CAAC,IAAI;oBACT,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IAED,OAAO;QACL,WAAW;QACX,IAAI;QACJ,IAAI;QACJ,UAAU;QACV,YAAY,EAAE,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC;QAC1C,SAAS;QACT,WAAW,EAAE,UAAU,CAAC,IAAI,GAAG,CAAC;QAChC,SAAS;KACV,CAAC;AACJ,CAAC,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,MAAa,uBAAuB;aAClB,SAAI,GAAG,GAAG,+BAAsB,yBAAyB,CAAC;aAE1D,SAAI,GAAoB;QACtC,IAAI,EAAE;YACJ,IAAI,EAAE,YAAY;YAClB,OAAO,EAAE,MAAM;YACf,MAAM,EAAE,EAAE;YACV,QAAQ,EAAE;gBACR,KAAK,EACH,6HAA6H;gBAC/H,UAAU,EACR,8LAA8L;aACjM;SACF;QACD,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE;YAClB,MAAM,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC;YAE/B,OAAO;gBACL,CAAC,qBAAY,CAAC,gBAAgB,CAAC,EAAE,CAAC,IAAe,EAAE,EAAE;oBACnD,MAAM,MAAM,GAAG,2CAAmB,CAAC,aAAa,CAAC;wBAC/C,IAAI,EAAE,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC;qBACnD,CAAC,CAAC;oBAEH,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;wBACzB,OAAO;oBACT,CAAC;oBAED,MAAM,IAAI,GAAG,OAAO,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;oBAEtD,OAAO,CAAC,MAAM,CAAC;wBACb,IAAI;wBACJ,SAAS,EAAE,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO;wBAC1D,IAAI,EAAE,EAAE,MAAM,EAAE;wBAChB,GAAG,EAAE,IAAI;4BACP,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE;gCACR,MAAM,MAAM,GAAG,4BAAY,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC;gCAC7E,MAAM,KAAK,GAAG,GAAG,MAAM,IAAI,CAAC;gCAC5B,oGAAoG;gCACpG,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC;gCAE3E,OAAO,KAAK,CAAC,WAAW,CACtB,IAAI,CAAC,WAAW,EAChB;oCACE,OAAO,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,UAAU,GAAG;oCACrC,GAAG,MAAM,OAAO;oCAChB,GAAG,KAAK,GAAG,IAAI,CAAC,IAAI,YAAY,IAAI,CAAC,YAAY,GAAG;oCACpD,GAAG,MAAM,KAAK,IAAI,IAAI;oCACtB,GAAG,KAAK,GAAG,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,SAAS,GAAG;oCAC3C,GAAG,MAAM,GAAG;iCACb,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;4BACJ,CAAC;4BACH,CAAC,CAAC,IAAI;qBACT,CAAC,CAAC;gBACL,CAAC;aACF,CAAC;QACJ,CAAC;KACF,CAAC;IAEF,MAAM,CAAC,KAAK,CAAC,OAAqC,EAAE;QAClD,OAAO,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC;IAClC,CAAC;;AA9DH,0DA+DC","sourcesContent":["import type { Rule, Scope, SourceCode } from 'eslint';\nimport type { TRuleSeverity } from '../rules/common';\nimport { AwaitSupport, STATEMENT_LISTS } from './await-support';\nimport { AstNode, AstNodeTypes, HOUSE_PLUGIN_NAMESPACE } from './common';\nimport { PromiseChainSupport } from './promise-chain-support';\n\n/** The catch variable the fix writes when the handler has no parameter. */\nconst CATCH_NAME = 'error';\n\n/** What the fix needs, read once from a `const x = await f().catch(h)` that passed every check. */\ninterface IFixPlan {\n declaration: Rule.Node;\n kind: string;\n name: string;\n annotation: string;\n receiverText: string;\n catchName: string;\n isErrorRead: boolean;\n valueText: string;\n}\n\n/** The identifiers a fallback value reads, and whether every node of it is a value the fix may move. */\nconst collectValue = (opts: {\n node: unknown;\n parameter: string | undefined;\n identifiers: unknown[];\n}): boolean => {\n const { node, parameter, identifiers } = opts;\n const type = AstNode.getType({ node }) ?? '';\n const value = (child: unknown) => collectValue({ node: child, parameter, identifiers });\n\n switch (type) {\n case 'Literal': {\n return true;\n }\n case 'Identifier': {\n identifiers.push(node);\n\n return true;\n }\n case 'TemplateLiteral': {\n return PromiseChainSupport.isConstant({ node });\n }\n case 'UnaryExpression': {\n return PromiseChainSupport.isConstant({ node });\n }\n case 'ChainExpression': {\n return value(AstNode.readField({ node, key: 'expression' }));\n }\n case 'MemberExpression': {\n // Only a read of the error itself: `error.message`, `error?.response.status`.\n const object = AstNode.readField({ node, key: 'object' });\n const isRead =\n AstNode.readField({ node, key: 'computed' }) !== true ||\n AstNode.getType({ node: AstNode.readField({ node, key: 'property' }) }) === 'Literal';\n const isRooted =\n AstNode.getType({ node: object }) === 'MemberExpression' ||\n (AstNode.getType({ node: object }) === 'Identifier' &&\n AstNode.readField({ node: object, key: 'name' }) === parameter);\n\n return isRead && isRooted && parameter !== undefined && value(object);\n }\n case 'ArrayExpression': {\n const elements = AstNode.readField({ node, key: 'elements' });\n\n return (\n Array.isArray(elements) && elements.every((element) => element === null || value(element))\n );\n }\n case 'ObjectExpression': {\n const properties = AstNode.readField({ node, key: 'properties' });\n\n return (\n Array.isArray(properties) &&\n properties.every(\n (property) =>\n AstNode.getType({ node: property }) === 'Property' &&\n AstNode.readField({ node: property, key: 'computed' }) !== true &&\n AstNode.readField({ node: property, key: 'method' }) !== true &&\n AstNode.readField({ node: property, key: 'kind' }) === 'init' &&\n value(AstNode.readField({ node: property, key: 'value' })),\n )\n );\n }\n default: {\n return false;\n }\n }\n};\n\n/** Whether `name` is declared in `scope` or any scope around it: a catch variable of that name would shadow it. */\nconst isDeclaredAround = (opts: { scope: Scope.Scope | null; name: string }): boolean => {\n for (let scope = opts.scope; scope; scope = scope.upper) {\n if (scope.set.has(opts.name)) {\n return true;\n }\n }\n\n return false;\n};\n\n/**\n * The plan of the fix for `awaitNode`, or `undefined` when the strict safe shape does not hold:\n * `const|let x[: T] = await f().catch(() => <value>)` or `.catch((error) => <value>)`, alone in its declaration,\n * in a statement list; `x` never written again and, without a type annotation, read only in its own function;\n * the handler an expression-bodied, non-async arrow with at most one plain parameter; `<value>` a literal, an\n * identifier, a read of the error (`error.message`) or an array or object literal of those; `f()` with no\n * `.then`, `.catch` or `.finally` before and no `await` inside; no comment the fix would drop.\n */\nconst planFix = (opts: { awaitNode: Rule.Node; sourceCode: SourceCode }): IFixPlan | undefined => {\n const { awaitNode, sourceCode } = opts;\n const call = AstNode.readField({ node: awaitNode, key: 'argument' });\n const callee = AstNode.readField({ node: call, key: 'callee' });\n const args = AstNode.readField({ node: call, key: 'arguments' });\n\n if (\n AstNode.getType({ node: call }) !== 'CallExpression' ||\n AstNode.readField({ node: call, key: 'optional' }) === true ||\n AstNode.getType({ node: callee }) !== 'MemberExpression' ||\n AstNode.readField({ node: callee, key: 'computed' }) === true ||\n AstNode.readField({ node: callee, key: 'optional' }) === true ||\n PromiseChainSupport.memberName({ member: callee }) !== 'catch' ||\n !Array.isArray(args) ||\n args.length !== 1\n ) {\n return undefined;\n }\n\n const handler: unknown = args[0];\n const params = AstNode.readField({ node: handler, key: 'params' });\n const body = AstNode.readField({ node: handler, key: 'body' });\n const parameter: unknown = Array.isArray(params) ? params[0] : undefined;\n\n if (\n AstNode.getType({ node: handler }) !== 'ArrowFunctionExpression' ||\n AstNode.readField({ node: handler, key: 'async' }) === true ||\n AstNode.getType({ node: body }) === AstNodeTypes.BLOCK_STATEMENT ||\n AstNode.readField({ node: handler, key: 'returnType' }) ||\n AstNode.readField({ node: handler, key: 'typeParameters' }) ||\n !Array.isArray(params) ||\n params.length > 1 ||\n (parameter !== undefined &&\n (AstNode.getType({ node: parameter }) !== 'Identifier' ||\n AstNode.readField({ node: parameter, key: 'typeAnnotation' }) ||\n AstNode.readField({ node: parameter, key: 'optional' }) === true))\n ) {\n return undefined;\n }\n\n const receiver = AstNode.readField({ node: callee, key: 'object' });\n\n if (\n !AwaitSupport.isNode(receiver) ||\n !AwaitSupport.isNode(body) ||\n !AwaitSupport.isNode(handler) ||\n PromiseChainSupport.hasChainOnSpine({ node: receiver }) ||\n /\\b(await|yield)\\b/.test(sourceCode.getText(receiver))\n ) {\n return undefined;\n }\n\n const declarator = AwaitSupport.parentOf({ node: awaitNode });\n const declaration = AwaitSupport.parentOf({ node: declarator });\n const id = AstNode.readField({ node: declarator, key: 'id' });\n const declarations = AstNode.readField({ node: declaration, key: 'declarations' });\n const kind = String(AstNode.readField({ node: declaration, key: 'kind' }));\n\n if (\n AstNode.getType({ node: declarator }) !== 'VariableDeclarator' ||\n AstNode.readField({ node: declarator, key: 'init' }) !== awaitNode ||\n AstNode.readField({ node: declarator, key: 'definite' }) === true ||\n AstNode.getType({ node: id }) !== 'Identifier' ||\n !AwaitSupport.isNode(declarator) ||\n !AwaitSupport.isNode(declaration) ||\n !Array.isArray(declarations) ||\n declarations.length !== 1 ||\n !['const', 'let'].includes(kind) ||\n !STATEMENT_LISTS.has(\n AstNode.getType({ node: AwaitSupport.parentOf({ node: declaration }) }) ?? '',\n )\n ) {\n return undefined;\n }\n\n const name = String(AstNode.readField({ node: id, key: 'name' }));\n const typeAnnotation = AstNode.readField({ node: id, key: 'typeAnnotation' });\n const annotation = AwaitSupport.isNode(typeAnnotation) ? sourceCode.getText(typeAnnotation) : '';\n\n // `let x;` with no annotation takes its type from the assignments that follow, so TypeScript must see every\n // read in the same function: a read from a nested function, an export or a `typeof` makes it an implicit any.\n const variable = sourceCode.getDeclaredVariables(declarator).find((entry) => entry.name === name);\n\n if (!variable) {\n return undefined;\n }\n\n for (const reference of variable.references) {\n if (reference.identifier === id) {\n continue;\n }\n\n const parentType = AstNode.getType({\n node: AwaitSupport.parentOf({ node: reference.identifier }),\n });\n\n if (\n reference.isWrite() ||\n (annotation === '' &&\n (reference.from.variableScope !== variable.scope.variableScope ||\n parentType === 'ExportSpecifier' ||\n parentType === 'TSTypeQuery'))\n ) {\n return undefined;\n }\n }\n\n const parameterName =\n parameter === undefined\n ? undefined\n : String(AstNode.readField({ node: parameter, key: 'name' }));\n const identifiers: unknown[] = [];\n\n if (!collectValue({ node: body, parameter: parameterName, identifiers })) {\n return undefined;\n }\n\n // `x = []` on a `let x;` with no annotation makes an evolving `any[]`, looser than the `never[]` it was.\n const elements = AstNode.readField({ node: body, key: 'elements' });\n\n if (\n annotation === '' &&\n AstNode.getType({ node: body }) === 'ArrayExpression' &&\n Array.isArray(elements) &&\n elements.length === 0\n ) {\n return undefined;\n }\n\n const parameterVariable = sourceCode\n .getDeclaredVariables(handler)\n .find((entry) => entry.name === parameterName);\n const errorReads = new Set<unknown>(\n parameterVariable?.references.map((reference) => reference.identifier) ?? [],\n );\n const freeNames = new Set(\n identifiers\n .filter((identifier) => !errorReads.has(identifier))\n .map((identifier) => String(AstNode.readField({ node: identifier, key: 'name' }))),\n );\n\n // The fallback is evaluated after the `let`: reading the declared name there would read `undefined`.\n if (freeNames.has(name)) {\n return undefined;\n }\n\n const scope = sourceCode.getScope(declaration);\n const isTaken = (candidate: string) =>\n candidate === name ||\n freeNames.has(candidate) ||\n (candidate !== parameterName && isDeclaredAround({ scope, name: candidate }));\n const base = parameterName ?? CATCH_NAME;\n let catchName = base;\n\n for (let index = 2; isTaken(catchName); index += 1) {\n catchName = `${base}${index}`;\n }\n\n const comments = sourceCode.getCommentsInside(declaration);\n const isInside = (range: [number, number] | undefined, inner: [number, number] | undefined) =>\n range !== undefined && inner !== undefined && range[0] <= inner[0] && inner[1] <= range[1];\n\n if (\n comments.some(\n (comment) => !isInside(receiver.range, comment.range) && !isInside(body.range, comment.range),\n )\n ) {\n return undefined;\n }\n\n const bodyStart = body.range?.[0] ?? 0;\n let valueText = sourceCode.getText(body);\n\n if (catchName !== parameterName && errorReads.size > 0) {\n const edits = [...errorReads]\n .filter(AwaitSupport.isNode)\n .map((identifier) => {\n const parent = AwaitSupport.parentOf({ node: identifier });\n const isShorthand =\n AstNode.getType({ node: parent }) === 'Property' &&\n AstNode.readField({ node: parent, key: 'shorthand' }) === true;\n\n return {\n range: identifier.range ?? [0, 0],\n text: isShorthand ? `${parameterName}: ${catchName}` : catchName,\n };\n })\n .sort((left, right) => right.range[0] - left.range[0]);\n\n for (const edit of edits) {\n valueText =\n valueText.slice(0, edit.range[0] - bodyStart) +\n edit.text +\n valueText.slice(edit.range[1] - bodyStart);\n }\n }\n\n return {\n declaration,\n kind,\n name,\n annotation,\n receiverText: sourceCode.getText(receiver),\n catchName,\n isErrorRead: errorReads.size > 0,\n valueText,\n };\n};\n\n/**\n * `venizia/no-await-promise-chain`. One expression uses one async style: `await` (in a try/catch when it can\n * fail), or a promise chain that is not awaited. An `await` whose operand - after parentheses, `!`, `as`,\n * `satisfies` and an optional chain - is a call of `.then`, `.catch` or `.finally` (`?.then(`, `['then'](`, a\n * thenable such as a query builder) is reported once, however long the chain. A chain that is returned or stands\n * as a statement is not awaited and is not reported, nor is `await Promise.all(xs.map(f))`, `await new Promise(...)`,\n * `await x.then` (no call), or an `await` inside a callback of a chain.\n *\n * The fix is made for one shape only, `const|let x = await f().catch(() => <value>)` (see `planFix` for every\n * condition), and writes `let x; try { x = await f(); } catch (error) { x = <value>; }` (`catch { ... }` when the value does not read the error): the `const` becomes a\n * `let`, a type annotation stays, the catch variable takes the handler's parameter name (`error` without one,\n * renamed when the name is taken), and is typed `any` when the value reads it, as the handler's parameter was.\n * The try also catches a synchronous throw of `f()`, which the chain let through. Everything else is reported.\n */\nexport class NoAwaitPromiseChainRule {\n static readonly NAME = `${HOUSE_PLUGIN_NAMESPACE}/no-await-promise-chain`;\n\n static readonly RULE: Rule.RuleModule = {\n meta: {\n type: 'suggestion',\n fixable: 'code',\n schema: [],\n messages: {\n mixed:\n 'Do not `await` a promise chain (`.{{method}}(...)`): wrap `await f()` in try/catch, or drop the `await` and keep the chain.',\n mixedConst:\n 'Do not `await` a promise chain (`.{{method}}(...)`): wrap `await f()` in try/catch, or drop the `await` and keep the chain. The fix writes the try/catch and turns the `const` into a `let`.',\n },\n },\n create: (context) => {\n const { sourceCode } = context;\n\n return {\n [AstNodeTypes.AWAIT_EXPRESSION]: (node: Rule.Node) => {\n const method = PromiseChainSupport.chainMethodOf({\n node: AstNode.readField({ node, key: 'argument' }),\n });\n\n if (method === undefined) {\n return;\n }\n\n const plan = planFix({ awaitNode: node, sourceCode });\n\n context.report({\n node,\n messageId: plan?.kind === 'const' ? 'mixedConst' : 'mixed',\n data: { method },\n fix: plan\n ? (fixer) => {\n const indent = AwaitSupport.indentOf({ node: plan.declaration, sourceCode });\n const inner = `${indent} `;\n // The optional catch binding when nothing reads the error: a named one would be an unused variable.\n const head = plan.isErrorRead ? `catch (${plan.catchName}: any)` : 'catch';\n\n return fixer.replaceText(\n plan.declaration,\n [\n `let ${plan.name}${plan.annotation};`,\n `${indent}try {`,\n `${inner}${plan.name} = await ${plan.receiverText};`,\n `${indent}} ${head} {`,\n `${inner}${plan.name} = ${plan.valueText};`,\n `${indent}}`,\n ].join('\\n'),\n );\n }\n : null,\n });\n },\n };\n },\n };\n\n static build(opts: { severity?: TRuleSeverity } = {}): TRuleSeverity {\n return opts.severity ?? 'error';\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"no-await-promise-chain.rule.js","sourceRoot":"","sources":["../../../src/linters/house/no-await-promise-chain.rule.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Rule, Scope, SourceCode } from 'eslint';\nimport type { TRuleSeverity } from '../rules/common';\nimport { AwaitSupport, STATEMENT_LISTS } from './await-support';\nimport { AstNode, AstNodeTypes, HOUSE_PLUGIN_NAMESPACE } from './common';\nimport { PromiseChainSupport } from './promise-chain-support';\n\n/** The catch variable the fix writes when the handler has no parameter. */\nconst CATCH_NAME = 'error';\n\n/** What the fix needs, read once from a `const x = await f().catch(h)` that passed every check. */\ninterface IFixPlan {\n declaration: Rule.Node;\n kind: string;\n name: string;\n annotation: string;\n receiverText: string;\n catchName: string;\n isErrorRead: boolean;\n valueText: string;\n}\n\n/** The identifiers a fallback value reads, and whether every node of it is a value the fix may move. */\nconst collectValue = (opts: {\n node: unknown;\n parameter: string | undefined;\n identifiers: unknown[];\n}): boolean => {\n const { node, parameter, identifiers } = opts;\n const type = AstNode.getType({ node }) ?? '';\n const value = (child: unknown) => collectValue({ node: child, parameter, identifiers });\n\n switch (type) {\n case AstNodeTypes.LITERAL: {\n return true;\n }\n case AstNodeTypes.IDENTIFIER: {\n identifiers.push(node);\n\n return true;\n }\n case AstNodeTypes.TEMPLATE_LITERAL: {\n return PromiseChainSupport.isConstant({ node });\n }\n case AstNodeTypes.UNARY_EXPRESSION: {\n return PromiseChainSupport.isConstant({ node });\n }\n case AstNodeTypes.CHAIN_EXPRESSION: {\n return value(AstNode.readField({ node, key: 'expression' }));\n }\n case AstNodeTypes.MEMBER_EXPRESSION: {\n // Only a read of the error itself: `error.message`, `error?.response.status`.\n const object = AstNode.readField({ node, key: 'object' });\n const isRead =\n AstNode.readField({ node, key: 'computed' }) !== true ||\n AstNode.getType({ node: AstNode.readField({ node, key: 'property' }) }) ===\n AstNodeTypes.LITERAL;\n const isRooted =\n AstNode.getType({ node: object }) === AstNodeTypes.MEMBER_EXPRESSION ||\n (AstNode.getType({ node: object }) === AstNodeTypes.IDENTIFIER &&\n AstNode.readField({ node: object, key: 'name' }) === parameter);\n\n return isRead && isRooted && parameter !== undefined && value(object);\n }\n case AstNodeTypes.ARRAY_EXPRESSION: {\n const elements = AstNode.readField({ node, key: 'elements' });\n\n return (\n Array.isArray(elements) && elements.every((element) => element === null || value(element))\n );\n }\n case AstNodeTypes.OBJECT_EXPRESSION: {\n const properties = AstNode.readField({ node, key: 'properties' });\n\n return (\n Array.isArray(properties) &&\n properties.every(\n (property) =>\n AstNode.getType({ node: property }) === AstNodeTypes.PROPERTY &&\n AstNode.readField({ node: property, key: 'computed' }) !== true &&\n AstNode.readField({ node: property, key: 'method' }) !== true &&\n AstNode.readField({ node: property, key: 'kind' }) === 'init' &&\n value(AstNode.readField({ node: property, key: 'value' })),\n )\n );\n }\n default: {\n return false;\n }\n }\n};\n\n/** Whether `name` is declared in `scope` or any scope around it: a catch variable of that name would shadow it. */\nconst isDeclaredAround = (opts: { scope: Scope.Scope | null; name: string }): boolean => {\n for (let scope = opts.scope; scope; scope = scope.upper) {\n if (scope.set.has(opts.name)) {\n return true;\n }\n }\n\n return false;\n};\n\n/**\n * The plan of the fix for `awaitNode`, or `undefined` when the strict safe shape does not hold:\n * `const|let x[: T] = await f().catch(() => <value>)` or `.catch((error) => <value>)`, alone in its declaration,\n * in a statement list; `x` never written again and, without a type annotation, read only in its own function;\n * the handler an expression-bodied, non-async arrow with at most one plain parameter; `<value>` a literal, an\n * identifier, a read of the error (`error.message`) or an array or object literal of those; `f()` with no\n * `.then`, `.catch` or `.finally` before and no `await` inside; no comment the fix would drop.\n */\nconst planFix = (opts: { awaitNode: Rule.Node; sourceCode: SourceCode }): IFixPlan | undefined => {\n const { awaitNode, sourceCode } = opts;\n const call = AstNode.readField({ node: awaitNode, key: 'argument' });\n const callee = AstNode.readField({ node: call, key: 'callee' });\n const args = AstNode.readField({ node: call, key: 'arguments' });\n\n if (\n AstNode.getType({ node: call }) !== AstNodeTypes.CALL_EXPRESSION ||\n AstNode.readField({ node: call, key: 'optional' }) === true ||\n AstNode.getType({ node: callee }) !== AstNodeTypes.MEMBER_EXPRESSION ||\n AstNode.readField({ node: callee, key: 'computed' }) === true ||\n AstNode.readField({ node: callee, key: 'optional' }) === true ||\n PromiseChainSupport.memberName({ member: callee }) !== 'catch' ||\n !Array.isArray(args) ||\n args.length !== 1\n ) {\n return undefined;\n }\n\n const handler: unknown = args[0];\n const params = AstNode.readField({ node: handler, key: 'params' });\n const body = AstNode.readField({ node: handler, key: 'body' });\n const parameter: unknown = Array.isArray(params) ? params[0] : undefined;\n\n if (\n AstNode.getType({ node: handler }) !== AstNodeTypes.ARROW_FUNCTION_EXPRESSION ||\n AstNode.readField({ node: handler, key: 'async' }) === true ||\n AstNode.getType({ node: body }) === AstNodeTypes.BLOCK_STATEMENT ||\n AstNode.readField({ node: handler, key: 'returnType' }) ||\n AstNode.readField({ node: handler, key: 'typeParameters' }) ||\n !Array.isArray(params) ||\n params.length > 1 ||\n (parameter !== undefined &&\n (AstNode.getType({ node: parameter }) !== AstNodeTypes.IDENTIFIER ||\n AstNode.readField({ node: parameter, key: 'typeAnnotation' }) ||\n AstNode.readField({ node: parameter, key: 'optional' }) === true))\n ) {\n return undefined;\n }\n\n const receiver = AstNode.readField({ node: callee, key: 'object' });\n\n if (\n !AwaitSupport.isNode(receiver) ||\n !AwaitSupport.isNode(body) ||\n !AwaitSupport.isNode(handler) ||\n PromiseChainSupport.hasChainOnSpine({ node: receiver }) ||\n /\\b(await|yield)\\b/.test(sourceCode.getText(receiver))\n ) {\n return undefined;\n }\n\n const declarator = AwaitSupport.parentOf({ node: awaitNode });\n const declaration = AwaitSupport.parentOf({ node: declarator });\n const id = AstNode.readField({ node: declarator, key: 'id' });\n const declarations = AstNode.readField({ node: declaration, key: 'declarations' });\n const kind = String(AstNode.readField({ node: declaration, key: 'kind' }));\n\n if (\n AstNode.getType({ node: declarator }) !== AstNodeTypes.VARIABLE_DECLARATOR ||\n AstNode.readField({ node: declarator, key: 'init' }) !== awaitNode ||\n AstNode.readField({ node: declarator, key: 'definite' }) === true ||\n AstNode.getType({ node: id }) !== AstNodeTypes.IDENTIFIER ||\n !AwaitSupport.isNode(declarator) ||\n !AwaitSupport.isNode(declaration) ||\n !Array.isArray(declarations) ||\n declarations.length !== 1 ||\n !['const', 'let'].includes(kind) ||\n !STATEMENT_LISTS.has(\n AstNode.getType({ node: AwaitSupport.parentOf({ node: declaration }) }) ?? '',\n )\n ) {\n return undefined;\n }\n\n const name = String(AstNode.readField({ node: id, key: 'name' }));\n const typeAnnotation = AstNode.readField({ node: id, key: 'typeAnnotation' });\n const annotation = AwaitSupport.isNode(typeAnnotation) ? sourceCode.getText(typeAnnotation) : '';\n\n // `let x;` with no annotation takes its type from the assignments that follow, so TypeScript must see every\n // read in the same function: a read from a nested function, an export or a `typeof` makes it an implicit any.\n const variable = sourceCode.getDeclaredVariables(declarator).find((entry) => entry.name === name);\n\n if (!variable) {\n return undefined;\n }\n\n for (const reference of variable.references) {\n if (reference.identifier === id) {\n continue;\n }\n\n const parentType = AstNode.getType({\n node: AwaitSupport.parentOf({ node: reference.identifier }),\n });\n\n if (\n reference.isWrite() ||\n (annotation === '' &&\n (reference.from.variableScope !== variable.scope.variableScope ||\n parentType === AstNodeTypes.EXPORT_SPECIFIER ||\n parentType === AstNodeTypes.TYPE_QUERY))\n ) {\n return undefined;\n }\n }\n\n const parameterName =\n parameter === undefined\n ? undefined\n : String(AstNode.readField({ node: parameter, key: 'name' }));\n const identifiers: unknown[] = [];\n\n if (!collectValue({ node: body, parameter: parameterName, identifiers })) {\n return undefined;\n }\n\n // `x = []` on a `let x;` with no annotation makes an evolving `any[]`, looser than the `never[]` it was.\n const elements = AstNode.readField({ node: body, key: 'elements' });\n\n if (\n annotation === '' &&\n AstNode.getType({ node: body }) === AstNodeTypes.ARRAY_EXPRESSION &&\n Array.isArray(elements) &&\n elements.length === 0\n ) {\n return undefined;\n }\n\n const parameterVariable = sourceCode\n .getDeclaredVariables(handler)\n .find((entry) => entry.name === parameterName);\n const errorReads = new Set<unknown>(\n parameterVariable?.references.map((reference) => reference.identifier) ?? [],\n );\n const freeNames = new Set(\n identifiers\n .filter((identifier) => !errorReads.has(identifier))\n .map((identifier) => String(AstNode.readField({ node: identifier, key: 'name' }))),\n );\n\n // The fallback is evaluated after the `let`: reading the declared name there would read `undefined`.\n if (freeNames.has(name)) {\n return undefined;\n }\n\n const scope = sourceCode.getScope(declaration);\n const isTaken = (candidate: string) =>\n candidate === name ||\n freeNames.has(candidate) ||\n (candidate !== parameterName && isDeclaredAround({ scope, name: candidate }));\n const base = parameterName ?? CATCH_NAME;\n let catchName = base;\n\n for (let index = 2; isTaken(catchName); index += 1) {\n catchName = `${base}${index}`;\n }\n\n const comments = sourceCode.getCommentsInside(declaration);\n const isInside = (range: [number, number] | undefined, inner: [number, number] | undefined) =>\n range !== undefined && inner !== undefined && range[0] <= inner[0] && inner[1] <= range[1];\n\n if (\n comments.some(\n (comment) => !isInside(receiver.range, comment.range) && !isInside(body.range, comment.range),\n )\n ) {\n return undefined;\n }\n\n const bodyStart = body.range?.[0] ?? 0;\n let valueText = sourceCode.getText(body);\n\n if (catchName !== parameterName && errorReads.size > 0) {\n const edits = [...errorReads]\n .filter(AwaitSupport.isNode)\n .map((identifier) => {\n const parent = AwaitSupport.parentOf({ node: identifier });\n const isShorthand =\n AstNode.getType({ node: parent }) === AstNodeTypes.PROPERTY &&\n AstNode.readField({ node: parent, key: 'shorthand' }) === true;\n\n return {\n range: identifier.range ?? [0, 0],\n text: isShorthand ? `${parameterName}: ${catchName}` : catchName,\n };\n })\n .sort((left, right) => right.range[0] - left.range[0]);\n\n for (const edit of edits) {\n valueText =\n valueText.slice(0, edit.range[0] - bodyStart) +\n edit.text +\n valueText.slice(edit.range[1] - bodyStart);\n }\n }\n\n return {\n declaration,\n kind,\n name,\n annotation,\n receiverText: sourceCode.getText(receiver),\n catchName,\n isErrorRead: errorReads.size > 0,\n valueText,\n };\n};\n\n/**\n * `venizia/no-await-promise-chain`. One expression uses one async style: `await` (in a try/catch when it can\n * fail), or a promise chain that is not awaited. An `await` whose operand - after parentheses, `!`, `as`,\n * `satisfies` and an optional chain - is a call of `.then`, `.catch` or `.finally` (`?.then(`, `['then'](`, a\n * thenable such as a query builder) is reported once, however long the chain. A chain that is returned or stands\n * as a statement is not awaited and is not reported, nor is `await Promise.all(xs.map(f))`, `await new Promise(...)`,\n * `await x.then` (no call), or an `await` inside a callback of a chain.\n *\n * The fix is made for one shape only, `const|let x = await f().catch(() => <value>)` (see `planFix` for every\n * condition), and writes `let x; try { x = await f(); } catch (error) { x = <value>; }` (`catch { ... }` when the value does not read the error): the `const` becomes a\n * `let`, a type annotation stays, the catch variable takes the handler's parameter name (`error` without one,\n * renamed when the name is taken), and is typed `any` when the value reads it, as the handler's parameter was.\n * The try also catches a synchronous throw of `f()`, which the chain let through. Everything else is reported.\n */\nexport class NoAwaitPromiseChainRule {\n static readonly NAME = `${HOUSE_PLUGIN_NAMESPACE}/no-await-promise-chain`;\n\n static readonly RULE: Rule.RuleModule = {\n meta: {\n type: 'suggestion',\n fixable: 'code',\n schema: [],\n messages: {\n mixed:\n 'Do not `await` a promise chain (`.{{method}}(...)`): wrap `await f()` in try/catch, or drop the `await` and keep the chain.',\n mixedConst:\n 'Do not `await` a promise chain (`.{{method}}(...)`): wrap `await f()` in try/catch, or drop the `await` and keep the chain. The fix writes the try/catch and turns the `const` into a `let`.',\n },\n },\n create: (context) => {\n const { sourceCode } = context;\n\n return {\n [AstNodeTypes.AWAIT_EXPRESSION]: (node: Rule.Node) => {\n const method = PromiseChainSupport.chainMethodOf({\n node: AstNode.readField({ node, key: 'argument' }),\n });\n\n if (method === undefined) {\n return;\n }\n\n const plan = planFix({ awaitNode: node, sourceCode });\n\n context.report({\n node,\n messageId: plan?.kind === 'const' ? 'mixedConst' : 'mixed',\n data: { method },\n fix: plan\n ? (fixer) => {\n const indent = AwaitSupport.indentOf({ node: plan.declaration, sourceCode });\n const inner = `${indent} `;\n // The optional catch binding when nothing reads the error: a named one would be an unused variable.\n const head = plan.isErrorRead ? `catch (${plan.catchName}: any)` : 'catch';\n\n return fixer.replaceText(\n plan.declaration,\n [\n `let ${plan.name}${plan.annotation};`,\n `${indent}try {`,\n `${inner}${plan.name} = await ${plan.receiverText};`,\n `${indent}} ${head} {`,\n `${inner}${plan.name} = ${plan.valueText};`,\n `${indent}}`,\n ].join('\\n'),\n );\n }\n : null,\n });\n },\n };\n },\n };\n\n static build(opts: { severity?: TRuleSeverity } = {}): TRuleSeverity {\n return opts.severity ?? 'error';\n }\n}\n"]}
|
|
@@ -30,11 +30,12 @@ class NoInlineAwaitRule {
|
|
|
30
30
|
[common_1.AstNodeTypes.AWAIT_EXPRESSION]: (node) => {
|
|
31
31
|
const parent = await_support_1.AwaitSupport.parentOf({ node });
|
|
32
32
|
const parentType = common_1.AstNode.getType({ node: parent });
|
|
33
|
-
const isWhole = (parentType ===
|
|
33
|
+
const isWhole = (parentType === common_1.AstNodeTypes.EXPRESSION_STATEMENT &&
|
|
34
34
|
common_1.AstNode.readField({ node: parent, key: 'expression' }) === node) ||
|
|
35
|
-
(parentType ===
|
|
35
|
+
(parentType === common_1.AstNodeTypes.VARIABLE_DECLARATOR &&
|
|
36
36
|
common_1.AstNode.readField({ node: parent, key: 'init' }) === node);
|
|
37
|
-
const isReturned = (parentType ===
|
|
37
|
+
const isReturned = (parentType === common_1.AstNodeTypes.RETURN_STATEMENT ||
|
|
38
|
+
parentType === common_1.AstNodeTypes.ARROW_FUNCTION_EXPRESSION) &&
|
|
38
39
|
(common_1.AstNode.readField({ node: parent, key: 'argument' }) === node ||
|
|
39
40
|
common_1.AstNode.readField({ node: parent, key: 'body' }) === node);
|
|
40
41
|
if (isWhole || isReturned) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-inline-await.rule.js","sourceRoot":"","sources":["../../../src/linters/house/no-inline-await.rule.ts"],"names":[],"mappings":";;;AAEA,mDAA+C;AAC/C,qCAAyE;AAEzE;;;;;;;;;GASG;AACH,MAAa,iBAAiB;aACZ,SAAI,GAAG,GAAG,+BAAsB,kBAAkB,CAAC;aAEnD,SAAI,GAAoB;QACtC,IAAI,EAAE;YACJ,IAAI,EAAE,YAAY;YAClB,OAAO,EAAE,MAAM;YACf,MAAM,EAAE,EAAE;YACV,QAAQ,EAAE;gBACR,MAAM,EACJ,2IAA2I;aAC9I;SACF;QACD,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE;YAClB,MAAM,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC;YAE/B,OAAO;gBACL,CAAC,qBAAY,CAAC,gBAAgB,CAAC,EAAE,CAAC,IAAe,EAAE,EAAE;oBACnD,MAAM,MAAM,GAAG,4BAAY,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;oBAC/C,MAAM,UAAU,GAAG,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;oBACrD,MAAM,OAAO,GACX,CAAC,UAAU,KAAK,
|
|
1
|
+
{"version":3,"file":"no-inline-await.rule.js","sourceRoot":"","sources":["../../../src/linters/house/no-inline-await.rule.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Rule } from 'eslint';\nimport type { TRuleSeverity } from '../rules/common';\nimport { AwaitSupport } from './await-support';\nimport { AstNode, AstNodeTypes, HOUSE_PLUGIN_NAMESPACE } from './common';\n\n/**\n * `venizia/no-inline-await`. `await` stands alone: as a whole statement (`await f();`) or as the whole initializer\n * of a declaration (`const result = await f();`). Inside any other expression - a call argument, a spread, an\n * array or object, a ternary, a logical operator, a template literal, a member access, an assignment - it is\n * reported, and `return g(await f())` is the same report. `return await f()` is `no-return-await`'s.\n *\n * The fix moves the `await` into a `const` in front of the statement. It is made only when nothing that does more\n * than read a value runs before the `await` inside the statement, and when the `await` is not in a branch, a loop\n * test, an unbraced `if` branch or an arrow expression body; those cases are reported and left alone.\n */\nexport class NoInlineAwaitRule {\n static readonly NAME = `${HOUSE_PLUGIN_NAMESPACE}/no-inline-await`;\n\n static readonly RULE: Rule.RuleModule = {\n meta: {\n type: 'suggestion',\n fixable: 'code',\n schema: [],\n messages: {\n inline:\n '`await` stands alone as a statement or as the whole initializer of a declaration (`const result = await f();`), not inside an expression.',\n },\n },\n create: (context) => {\n const { sourceCode } = context;\n\n return {\n [AstNodeTypes.AWAIT_EXPRESSION]: (node: Rule.Node) => {\n const parent = AwaitSupport.parentOf({ node });\n const parentType = AstNode.getType({ node: parent });\n const isWhole =\n (parentType === AstNodeTypes.EXPRESSION_STATEMENT &&\n AstNode.readField({ node: parent, key: 'expression' }) === node) ||\n (parentType === AstNodeTypes.VARIABLE_DECLARATOR &&\n AstNode.readField({ node: parent, key: 'init' }) === node);\n const isReturned =\n (parentType === AstNodeTypes.RETURN_STATEMENT ||\n parentType === AstNodeTypes.ARROW_FUNCTION_EXPRESSION) &&\n (AstNode.readField({ node: parent, key: 'argument' }) === node ||\n AstNode.readField({ node: parent, key: 'body' }) === node);\n\n if (isWhole || isReturned) {\n return;\n }\n\n const statement = AwaitSupport.hoistTarget({ awaitNode: node });\n const canFix =\n statement !== undefined &&\n !AwaitSupport.hasEffectBefore({ statement, awaitNode: node, sourceCode });\n\n context.report({\n node,\n messageId: 'inline',\n fix: canFix\n ? (fixer) => {\n const name = AwaitSupport.freshName({ node, base: 'result', sourceCode });\n const [start, end] = AwaitSupport.replaceRangeOf({ awaitNode: node, sourceCode });\n const indent = AwaitSupport.indentOf({ node: statement, sourceCode });\n\n return [\n fixer.insertTextBefore(\n statement,\n `const ${name} = ${sourceCode.getText(node)};\\n${indent}`,\n ),\n fixer.replaceTextRange([start, end], name),\n ];\n }\n : null,\n });\n },\n };\n },\n };\n\n static build(opts: { severity?: TRuleSeverity } = {}): TRuleSeverity {\n return opts.severity ?? 'error';\n }\n}\n"]}
|