@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,8 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.NoLeakedRenderRule = void 0;
|
|
4
4
|
const common_1 = require("./common");
|
|
5
5
|
/** `&&` directly under a JSX child: `disabled={a && b}` is a value, not something drawn. */
|
|
6
|
-
const LEAKED_RENDER_SELECTOR = [
|
|
7
|
-
.map((parent) => `${parent} >
|
|
6
|
+
const LEAKED_RENDER_SELECTOR = [common_1.AstNodeTypes.JSX_ELEMENT, common_1.AstNodeTypes.JSX_FRAGMENT]
|
|
7
|
+
.map((parent) => `${parent} > ${common_1.AstNodeTypes.JSX_EXPRESSION_CONTAINER} > ${common_1.AstNodeTypes.LOGICAL_EXPRESSION}[operator='&&']`)
|
|
8
8
|
.join(', ');
|
|
9
9
|
/**
|
|
10
10
|
* `venizia/no-leaked-render`. `{count && <X />}` draws `0` when `count` is `0`; draw nothing with
|
|
@@ -24,7 +24,7 @@ class NoLeakedRenderRule {
|
|
|
24
24
|
},
|
|
25
25
|
create: (context) => ({
|
|
26
26
|
[LEAKED_RENDER_SELECTOR]: (node) => {
|
|
27
|
-
if (node.type !==
|
|
27
|
+
if (node.type !== common_1.AstNodeTypes.LOGICAL_EXPRESSION) {
|
|
28
28
|
return;
|
|
29
29
|
}
|
|
30
30
|
const source = context.sourceCode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-leaked-render.rule.js","sourceRoot":"","sources":["../../../src/linters/house/no-leaked-render.rule.ts"],"names":[],"mappings":";;;AAEA,
|
|
1
|
+
{"version":3,"file":"no-leaked-render.rule.js","sourceRoot":"","sources":["../../../src/linters/house/no-leaked-render.rule.ts"],"names":[],"mappings":";;;AAEA,qCAAgE;AAEhE,4FAA4F;AAC5F,MAAM,sBAAsB,GAAG,CAAC,qBAAY,CAAC,WAAW,EAAE,qBAAY,CAAC,YAAY,CAAC;KACjF,GAAG,CACF,CAAC,MAAM,EAAE,EAAE,CACT,GAAG,MAAM,MAAM,qBAAY,CAAC,wBAAwB,MAAM,qBAAY,CAAC,kBAAkB,iBAAiB,CAC7G;KACA,IAAI,CAAC,IAAI,CAAC,CAAC;AAEd;;;;GAIG;AACH,MAAa,kBAAkB;aACb,SAAI,GAAG,GAAG,+BAAsB,mBAAmB,CAAC;aAEpD,SAAI,GAAoB;QACtC,IAAI,EAAE;YACJ,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,MAAM;YACf,MAAM,EAAE,EAAE;YACV,QAAQ,EAAE;gBACR,MAAM,EAAE,uEAAuE;aAChF;SACF;QACD,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YACpB,CAAC,sBAAsB,CAAC,EAAE,CAAC,IAAe,EAAE,EAAE;gBAC5C,IAAI,IAAI,CAAC,IAAI,KAAK,qBAAY,CAAC,kBAAkB,EAAE,CAAC;oBAClD,OAAO;gBACT,CAAC;gBAED,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;gBAClC,MAAM,QAAQ,GAAG,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC;gBAElF,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACd,OAAO;gBACT,CAAC;gBAED,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC3E,OAAO,CAAC,MAAM,CAAC;oBACb,IAAI;oBACJ,SAAS,EAAE,QAAQ;oBACnB,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC;iBAC1F,CAAC,CAAC;YACL,CAAC;SACF,CAAC;KACH,CAAC;IAEF,MAAM,CAAC,KAAK,CAAC,OAAqC,EAAE;QAClD,OAAO,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC;IAClC,CAAC;;AArCH,gDAsCC","sourcesContent":["import type { Rule } from 'eslint';\nimport type { TRuleSeverity } from '../rules/common';\nimport { AstNodeTypes, HOUSE_PLUGIN_NAMESPACE } from './common';\n\n/** `&&` directly under a JSX child: `disabled={a && b}` is a value, not something drawn. */\nconst LEAKED_RENDER_SELECTOR = [AstNodeTypes.JSX_ELEMENT, AstNodeTypes.JSX_FRAGMENT]\n .map(\n (parent) =>\n `${parent} > ${AstNodeTypes.JSX_EXPRESSION_CONTAINER} > ${AstNodeTypes.LOGICAL_EXPRESSION}[operator='&&']`,\n )\n .join(', ');\n\n/**\n * `venizia/no-leaked-render`. `{count && <X />}` draws `0` when `count` is `0`; draw nothing with\n * `cond ? <X /> : null`. Only a child of JSX is checked. The fix rewrites it to the ternary and keeps\n * any comment between `&&` and the drawn part.\n */\nexport class NoLeakedRenderRule {\n static readonly NAME = `${HOUSE_PLUGIN_NAMESPACE}/no-leaked-render`;\n\n static readonly RULE: Rule.RuleModule = {\n meta: {\n type: 'problem',\n fixable: 'code',\n schema: [],\n messages: {\n leaked: 'Draw nothing with `cond ? <X /> : null`; `&&` draws 0 when cond is 0.',\n },\n },\n create: (context) => ({\n [LEAKED_RENDER_SELECTOR]: (node: Rule.Node) => {\n if (node.type !== AstNodeTypes.LOGICAL_EXPRESSION) {\n return;\n }\n\n const source = context.sourceCode;\n const operator = source.getTokenAfter(node.left, (token) => token.value === '&&');\n\n if (!operator) {\n return;\n }\n\n const drawn = source.text.slice(operator.range[1], node.range?.[1]).trim();\n context.report({\n node,\n messageId: 'leaked',\n fix: (fixer) => fixer.replaceText(node, `${source.getText(node.left)} ? ${drawn} : null`),\n });\n },\n }),\n };\n\n static build(opts: { severity?: TRuleSeverity } = {}): TRuleSeverity {\n return opts.severity ?? 'error';\n }\n}\n"]}
|
|
@@ -19,7 +19,7 @@ class NoNewErrorRule {
|
|
|
19
19
|
},
|
|
20
20
|
create: (context) => {
|
|
21
21
|
const report = (opts) => context.report({ node: opts.node, messageId: 'newError', data: { form: opts.form } });
|
|
22
|
-
const isErrorIdentifier = (callee) => common_1.AstNode.getType({ node: callee }) ===
|
|
22
|
+
const isErrorIdentifier = (callee) => common_1.AstNode.getType({ node: callee }) === common_1.AstNodeTypes.IDENTIFIER &&
|
|
23
23
|
common_1.AstNode.readField({ node: callee, key: 'name' }) === 'Error';
|
|
24
24
|
return {
|
|
25
25
|
[common_1.AstNodeTypes.NEW_EXPRESSION]: (node) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-new-error.rule.js","sourceRoot":"","sources":["../../../src/linters/house/no-new-error.rule.ts"],"names":[],"mappings":";;;AAEA,qCAAyE;AAEzE;;;;GAIG;AACH,MAAa,cAAc;aACT,SAAI,GAAG,GAAG,+BAAsB,eAAe,CAAC;aAEhD,SAAI,GAAoB;QACtC,IAAI,EAAE;YACJ,IAAI,EAAE,SAAS;YACf,MAAM,EAAE,EAAE;YACV,QAAQ,EAAE;gBACR,QAAQ,EACN,2IAA2I;aAC9I;SACF;QACD,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE;YAClB,MAAM,MAAM,GAAG,CAAC,IAAuC,EAAE,EAAE,CACzD,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAExF,MAAM,iBAAiB,GAAG,CAAC,MAAe,EAAE,EAAE,CAC5C,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,KAAK,
|
|
1
|
+
{"version":3,"file":"no-new-error.rule.js","sourceRoot":"","sources":["../../../src/linters/house/no-new-error.rule.ts"],"names":[],"mappings":";;;AAEA,qCAAyE;AAEzE;;;;GAIG;AACH,MAAa,cAAc;aACT,SAAI,GAAG,GAAG,+BAAsB,eAAe,CAAC;aAEhD,SAAI,GAAoB;QACtC,IAAI,EAAE;YACJ,IAAI,EAAE,SAAS;YACf,MAAM,EAAE,EAAE;YACV,QAAQ,EAAE;gBACR,QAAQ,EACN,2IAA2I;aAC9I;SACF;QACD,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE;YAClB,MAAM,MAAM,GAAG,CAAC,IAAuC,EAAE,EAAE,CACzD,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAExF,MAAM,iBAAiB,GAAG,CAAC,MAAe,EAAE,EAAE,CAC5C,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,KAAK,qBAAY,CAAC,UAAU;gBAC7D,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC;YAE/D,OAAO;gBACL,CAAC,qBAAY,CAAC,cAAc,CAAC,EAAE,CAAC,IAAe,EAAE,EAAE;oBACjD,IAAI,iBAAiB,CAAC,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC;wBAClE,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC,CAAC;oBAC3C,CAAC;gBACH,CAAC;gBACD,CAAC,qBAAY,CAAC,eAAe,CAAC,EAAE,CAAC,IAAe,EAAE,EAAE;oBAClD,IAAI,iBAAiB,CAAC,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC;wBAClE,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC;oBACvC,CAAC;gBACH,CAAC;aACF,CAAC;QACJ,CAAC;KACF,CAAC;IAEF,MAAM,CAAC,KAAK,CAAC,OAAqC,EAAE;QAClD,OAAO,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC;IAClC,CAAC;;AArCH,wCAsCC","sourcesContent":["import type { Rule } from 'eslint';\nimport type { TRuleSeverity } from '../rules/common';\nimport { AstNode, AstNodeTypes, HOUSE_PLUGIN_NAMESPACE } from './common';\n\n/**\n * `venizia/no-new-error`. An error is thrown through `getError({ message })` (or an `ApplicationError`),\n * never `new Error(...)` or `Error(...)`: only an ApplicationError carries the status, the message code and\n * args, and the `extra` every IGNIS layer reads.\n */\nexport class NoNewErrorRule {\n static readonly NAME = `${HOUSE_PLUGIN_NAMESPACE}/no-new-error`;\n\n static readonly RULE: Rule.RuleModule = {\n meta: {\n type: 'problem',\n schema: [],\n messages: {\n newError:\n 'Throw through getError({ message }) (or an ApplicationError), not `{{form}}`: only an ApplicationError carries the status, code and args.',\n },\n },\n create: (context) => {\n const report = (opts: { node: Rule.Node; form: string }) =>\n context.report({ node: opts.node, messageId: 'newError', data: { form: opts.form } });\n\n const isErrorIdentifier = (callee: unknown) =>\n AstNode.getType({ node: callee }) === AstNodeTypes.IDENTIFIER &&\n AstNode.readField({ node: callee, key: 'name' }) === 'Error';\n\n return {\n [AstNodeTypes.NEW_EXPRESSION]: (node: Rule.Node) => {\n if (isErrorIdentifier(AstNode.readField({ node, key: 'callee' }))) {\n report({ node, form: 'new Error(...)' });\n }\n },\n [AstNodeTypes.CALL_EXPRESSION]: (node: Rule.Node) => {\n if (isErrorIdentifier(AstNode.readField({ node, key: 'callee' }))) {\n report({ node, form: 'Error(...)' });\n }\n },\n };\n },\n };\n\n static build(opts: { severity?: TRuleSeverity } = {}): TRuleSeverity {\n return opts.severity ?? 'error';\n }\n}\n"]}
|
|
@@ -7,7 +7,7 @@ const common_1 = require("./common");
|
|
|
7
7
|
const isInTry = (node) => {
|
|
8
8
|
let current = await_support_1.AwaitSupport.parentOf({ node });
|
|
9
9
|
while (current && !await_support_1.FUNCTION_TYPES.has(common_1.AstNode.getType({ node: current }) ?? '')) {
|
|
10
|
-
if (common_1.AstNode.getType({ node: current }) ===
|
|
10
|
+
if (common_1.AstNode.getType({ node: current }) === common_1.AstNodeTypes.TRY_STATEMENT) {
|
|
11
11
|
return true;
|
|
12
12
|
}
|
|
13
13
|
current = await_support_1.AwaitSupport.parentOf({ node: current });
|
|
@@ -35,7 +35,7 @@ class NoReturnAwaitRule {
|
|
|
35
35
|
const reportAwait = (opts) => {
|
|
36
36
|
const argument = common_1.AstNode.readField({ node: opts.awaitNode, key: 'argument' });
|
|
37
37
|
const argumentText = await_support_1.AwaitSupport.isNode(argument) &&
|
|
38
|
-
common_1.AstNode.getType({ node: argument }) !==
|
|
38
|
+
common_1.AstNode.getType({ node: argument }) !== common_1.AstNodeTypes.SEQUENCE_EXPRESSION
|
|
39
39
|
? sourceCode.getText(argument)
|
|
40
40
|
: undefined;
|
|
41
41
|
context.report({
|
|
@@ -65,13 +65,14 @@ class NoReturnAwaitRule {
|
|
|
65
65
|
[common_1.AstNodeTypes.RETURN_STATEMENT]: (node) => {
|
|
66
66
|
const argument = common_1.AstNode.readField({ node, key: 'argument' });
|
|
67
67
|
if (await_support_1.AwaitSupport.isNode(argument) &&
|
|
68
|
-
common_1.AstNode.getType({ node: argument }) ===
|
|
68
|
+
common_1.AstNode.getType({ node: argument }) === common_1.AstNodeTypes.AWAIT_EXPRESSION) {
|
|
69
69
|
reportAwait({ reported: node, awaitNode: argument, statement: node });
|
|
70
70
|
}
|
|
71
71
|
},
|
|
72
72
|
[common_1.AstNodeTypes.ARROW_FUNCTION_EXPRESSION]: (node) => {
|
|
73
73
|
const body = common_1.AstNode.readField({ node, key: 'body' });
|
|
74
|
-
if (await_support_1.AwaitSupport.isNode(body) &&
|
|
74
|
+
if (await_support_1.AwaitSupport.isNode(body) &&
|
|
75
|
+
common_1.AstNode.getType({ node: body }) === common_1.AstNodeTypes.AWAIT_EXPRESSION) {
|
|
75
76
|
reportAwait({ reported: node, awaitNode: body });
|
|
76
77
|
}
|
|
77
78
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-return-await.rule.js","sourceRoot":"","sources":["../../../src/linters/house/no-return-await.rule.ts"],"names":[],"mappings":";;;AAEA,mDAAgF;AAChF,qCAAyE;AAEzE,4EAA4E;AAC5E,MAAM,OAAO,GAAG,CAAC,IAAa,EAAW,EAAE;IACzC,IAAI,OAAO,GAAG,4BAAY,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IAE9C,OAAO,OAAO,IAAI,CAAC,8BAAc,CAAC,GAAG,CAAC,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;QAChF,IAAI,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,KAAK,
|
|
1
|
+
{"version":3,"file":"no-return-await.rule.js","sourceRoot":"","sources":["../../../src/linters/house/no-return-await.rule.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Rule } from 'eslint';\nimport type { TRuleSeverity } from '../rules/common';\nimport { AwaitSupport, FUNCTION_TYPES, STATEMENT_LISTS } from './await-support';\nimport { AstNode, AstNodeTypes, HOUSE_PLUGIN_NAMESPACE } from './common';\n\n/** `node` sits inside a `try`, `catch` or `finally` of its own function. */\nconst isInTry = (node: unknown): boolean => {\n let current = AwaitSupport.parentOf({ node });\n\n while (current && !FUNCTION_TYPES.has(AstNode.getType({ node: current }) ?? '')) {\n if (AstNode.getType({ node: current }) === AstNodeTypes.TRY_STATEMENT) {\n return true;\n }\n\n current = AwaitSupport.parentOf({ node: current });\n }\n\n return false;\n};\n\n/**\n * `venizia/no-return-await`. A function returns the promise (`return f()`), never `return await f()`. Where the\n * `await` matters (inside `try`, `catch` or `finally`) it is written on its own line:\n * `const result = await f(); return result;`. An arrow whose body is an `await` is the same: `() => f()`.\n */\nexport class NoReturnAwaitRule {\n static readonly NAME = `${HOUSE_PLUGIN_NAMESPACE}/no-return-await`;\n\n static readonly RULE: Rule.RuleModule = {\n meta: {\n type: 'suggestion',\n fixable: 'code',\n schema: [],\n messages: {\n returnAwait:\n 'Return the promise (`return f()`), not `return await f()`; where the await matters (inside try, catch or finally) write `const result = await f(); return result;`.',\n },\n },\n create: (context) => {\n const { sourceCode } = context;\n\n const reportAwait = (opts: {\n reported: Rule.Node;\n awaitNode: Rule.Node;\n statement?: Rule.Node;\n }) => {\n const argument = AstNode.readField({ node: opts.awaitNode, key: 'argument' });\n const argumentText =\n AwaitSupport.isNode(argument) &&\n AstNode.getType({ node: argument }) !== AstNodeTypes.SEQUENCE_EXPRESSION\n ? sourceCode.getText(argument)\n : undefined;\n\n context.report({\n node: opts.reported,\n messageId: 'returnAwait',\n fix:\n argumentText === undefined\n ? null\n : (fixer) => {\n if (!opts.statement || !isInTry(opts.statement)) {\n return fixer.replaceText(opts.awaitNode, argumentText);\n }\n\n const outer = AwaitSupport.parentOf({ node: opts.statement });\n\n if (!STATEMENT_LISTS.has(AstNode.getType({ node: outer }) ?? '')) {\n return null;\n }\n\n const name = AwaitSupport.freshName({\n node: opts.statement,\n base: 'result',\n sourceCode,\n });\n const indent = AwaitSupport.indentOf({ node: opts.statement, sourceCode });\n\n return fixer.replaceText(\n opts.statement,\n `const ${name} = await ${argumentText};\\n${indent}return ${name};`,\n );\n },\n });\n };\n\n return {\n [AstNodeTypes.RETURN_STATEMENT]: (node: Rule.Node) => {\n const argument = AstNode.readField({ node, key: 'argument' });\n\n if (\n AwaitSupport.isNode(argument) &&\n AstNode.getType({ node: argument }) === AstNodeTypes.AWAIT_EXPRESSION\n ) {\n reportAwait({ reported: node, awaitNode: argument, statement: node });\n }\n },\n [AstNodeTypes.ARROW_FUNCTION_EXPRESSION]: (node: Rule.Node) => {\n const body = AstNode.readField({ node, key: 'body' });\n\n if (\n AwaitSupport.isNode(body) &&\n AstNode.getType({ node: body }) === AstNodeTypes.AWAIT_EXPRESSION\n ) {\n reportAwait({ reported: node, awaitNode: body });\n }\n },\n };\n },\n };\n\n static build(opts: { severity?: TRuleSeverity } = {}): TRuleSeverity {\n return opts.severity ?? 'error';\n }\n}\n"]}
|
|
@@ -7,11 +7,11 @@ const promise_chain_support_1 = require("./promise-chain-support");
|
|
|
7
7
|
/** Whether a parameter of `owner` (a function or a catch clause) is read or written anywhere. */
|
|
8
8
|
const isParameterUsed = (opts) => opts.sourceCode
|
|
9
9
|
.getDeclaredVariables(opts.owner)
|
|
10
|
-
.some((variable) => variable.defs.some((definition) => ['Parameter',
|
|
10
|
+
.some((variable) => variable.defs.some((definition) => ['Parameter', common_1.AstNodeTypes.CATCH_CLAUSE].includes(definition.type)) && variable.references.length > 0);
|
|
11
11
|
/** A parameter that is not a plain name (`({ message }) =>`, `catch ({ message })`) reads the error by itself. */
|
|
12
12
|
const isPlainParameter = (opts) => opts.parameter === null ||
|
|
13
13
|
opts.parameter === undefined ||
|
|
14
|
-
common_1.AstNode.getType({ node: opts.parameter }) ===
|
|
14
|
+
common_1.AstNode.getType({ node: opts.parameter }) === common_1.AstNodeTypes.IDENTIFIER;
|
|
15
15
|
/**
|
|
16
16
|
* `venizia/no-silent-catch`. A handled error leaves a trace (V-C-06). Reported: a `.catch(h)` (also `?.catch`,
|
|
17
17
|
* `['catch']`) whose handler is an arrow or function expression that ignores its parameter and whose body is empty
|
|
@@ -46,7 +46,8 @@ class NoSilentCatchRule {
|
|
|
46
46
|
const handler = Array.isArray(args) ? args[0] : undefined;
|
|
47
47
|
const handlerType = common_1.AstNode.getType({ node: handler });
|
|
48
48
|
if (!await_support_1.AwaitSupport.isNode(handler) ||
|
|
49
|
-
(handlerType !==
|
|
49
|
+
(handlerType !== common_1.AstNodeTypes.ARROW_FUNCTION_EXPRESSION &&
|
|
50
|
+
handlerType !== common_1.AstNodeTypes.FUNCTION_EXPRESSION)) {
|
|
50
51
|
return;
|
|
51
52
|
}
|
|
52
53
|
const params = common_1.AstNode.readField({ node: handler, key: 'params' });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-silent-catch.rule.js","sourceRoot":"","sources":["../../../src/linters/house/no-silent-catch.rule.ts"],"names":[],"mappings":";;;AAEA,mDAA+C;AAC/C,qCAAyE;AACzE,mEAA8D;AAE9D,iGAAiG;AACjG,MAAM,eAAe,GAAG,CAAC,IAAkD,EAAW,EAAE,CACtF,IAAI,CAAC,UAAU;KACZ,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC;KAChC,IAAI,CACH,CAAC,QAAQ,EAAE,EAAE,CACX,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,EAAE,CAChC,CAAC,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"no-silent-catch.rule.js","sourceRoot":"","sources":["../../../src/linters/house/no-silent-catch.rule.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Rule, SourceCode } from 'eslint';\nimport type { TRuleSeverity } from '../rules/common';\nimport { AwaitSupport } from './await-support';\nimport { AstNode, AstNodeTypes, HOUSE_PLUGIN_NAMESPACE } from './common';\nimport { PromiseChainSupport } from './promise-chain-support';\n\n/** Whether a parameter of `owner` (a function or a catch clause) is read or written anywhere. */\nconst isParameterUsed = (opts: { owner: Rule.Node; sourceCode: SourceCode }): boolean =>\n opts.sourceCode\n .getDeclaredVariables(opts.owner)\n .some(\n (variable) =>\n variable.defs.some((definition) =>\n ['Parameter', AstNodeTypes.CATCH_CLAUSE].includes(definition.type),\n ) && variable.references.length > 0,\n );\n\n/** A parameter that is not a plain name (`({ message }) =>`, `catch ({ message })`) reads the error by itself. */\nconst isPlainParameter = (opts: { parameter: unknown }): boolean =>\n opts.parameter === null ||\n opts.parameter === undefined ||\n AstNode.getType({ node: opts.parameter }) === AstNodeTypes.IDENTIFIER;\n\n/**\n * `venizia/no-silent-catch`. A handled error leaves a trace (V-C-06). Reported: a `.catch(h)` (also `?.catch`,\n * `['catch']`) whose handler is an arrow or function expression that ignores its parameter and whose body is empty\n * or only gives back a constant (`() => null`, `() => undefined`, `() => ({})`, `() => []`, `() => {}`,\n * `function () {}`), and a `catch` block that is empty, holds only a comment, or only assigns or returns a constant\n * without reading the error. Handled, and not reported: anything that reads the error (logs, wraps or rethrows\n * it), makes any call (a log, a cleanup, a fallback), throws, or reads another variable.\n *\n * It is not ESLint's `no-empty`: `no-empty` reports an empty block only, lets a block that holds a comment pass,\n * and never sees `.catch(() => null)`. Both report `catch {}`, each with its own message. There is no fix: what to\n * log is a decision. A deliberate silent catch carries an `eslint-disable-next-line` with its reason.\n */\nexport class NoSilentCatchRule {\n static readonly NAME = `${HOUSE_PLUGIN_NAMESPACE}/no-silent-catch`;\n\n static readonly RULE: Rule.RuleModule = {\n meta: {\n type: 'suggestion',\n schema: [],\n messages: {\n silentHandler:\n 'This `.catch` handler swallows the error with no trace: log it, rethrow it or wrap it (V-C-06), or keep it with an `eslint-disable-next-line` and the reason.',\n silentBlock:\n 'This `catch` block swallows the error with no trace: log it, rethrow it or wrap it (V-C-06), or keep it with an `eslint-disable-next-line` and the reason.',\n },\n },\n create: (context) => {\n const { sourceCode } = context;\n\n return {\n [AstNodeTypes.CALL_EXPRESSION]: (node: Rule.Node) => {\n if (PromiseChainSupport.chainMethodOf({ node }) !== 'catch') {\n return;\n }\n\n const args = AstNode.readField({ node, key: 'arguments' });\n const handler: unknown = Array.isArray(args) ? args[0] : undefined;\n const handlerType = AstNode.getType({ node: handler });\n\n if (\n !AwaitSupport.isNode(handler) ||\n (handlerType !== AstNodeTypes.ARROW_FUNCTION_EXPRESSION &&\n handlerType !== AstNodeTypes.FUNCTION_EXPRESSION)\n ) {\n return;\n }\n\n const params = AstNode.readField({ node: handler, key: 'params' });\n\n if (\n !Array.isArray(params) ||\n !params.every((parameter) => isPlainParameter({ parameter })) ||\n isParameterUsed({ owner: handler, sourceCode })\n ) {\n return;\n }\n\n const body = AstNode.readField({ node: handler, key: 'body' });\n const isSilent =\n AstNode.getType({ node: body }) === AstNodeTypes.BLOCK_STATEMENT\n ? PromiseChainSupport.isSilentBlock({\n statements: AstNode.readField({ node: body, key: 'body' }),\n })\n : PromiseChainSupport.isConstant({ node: body });\n\n if (isSilent) {\n context.report({ node: handler, messageId: 'silentHandler' });\n }\n },\n [AstNodeTypes.CATCH_CLAUSE]: (node: Rule.Node) => {\n if (\n !isPlainParameter({ parameter: AstNode.readField({ node, key: 'param' }) }) ||\n isParameterUsed({ owner: node, sourceCode })\n ) {\n return;\n }\n\n const body = AstNode.readField({ node, key: 'body' });\n\n if (\n PromiseChainSupport.isSilentBlock({\n statements: AstNode.readField({ node: body, key: 'body' }),\n })\n ) {\n context.report({ node, messageId: 'silentBlock' });\n }\n },\n };\n },\n };\n\n static build(opts: { severity?: TRuleSeverity } = {}): TRuleSeverity {\n return opts.severity ?? 'error';\n }\n}\n"]}
|
|
@@ -5,11 +5,11 @@ const common_1 = require("./common");
|
|
|
5
5
|
const CHAIN_METHODS = new Set(['then', 'catch', 'finally']);
|
|
6
6
|
/** Wrappers that leave the value of the expression they hold unchanged: `x!`, `x as T`, `x satisfies T`, `<T>x`, `a?.b`. */
|
|
7
7
|
const VALUE_WRAPPERS = new Set([
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
common_1.AstNodeTypes.AS_EXPRESSION,
|
|
9
|
+
common_1.AstNodeTypes.SATISFIES_EXPRESSION,
|
|
10
|
+
common_1.AstNodeTypes.NON_NULL_EXPRESSION,
|
|
11
|
+
common_1.AstNodeTypes.TYPE_ASSERTION,
|
|
12
|
+
common_1.AstNodeTypes.CHAIN_EXPRESSION,
|
|
13
13
|
]);
|
|
14
14
|
const CONSTANT_UNARY_OPERATORS = new Set(['-', '+', '!', 'void']);
|
|
15
15
|
/** The shared parts of the promise chain rules: what a chain call is, what a constant is, what a silent handler body is. */
|
|
@@ -30,13 +30,13 @@ class PromiseChainSupport {
|
|
|
30
30
|
const name = common_1.AstNode.readField({ node: property, key: 'name' });
|
|
31
31
|
return typeof name === 'string' ? name : undefined;
|
|
32
32
|
}
|
|
33
|
-
if (common_1.AstNode.getType({ node: property }) ===
|
|
33
|
+
if (common_1.AstNode.getType({ node: property }) === common_1.AstNodeTypes.LITERAL) {
|
|
34
34
|
const value = common_1.AstNode.readField({ node: property, key: 'value' });
|
|
35
35
|
return typeof value === 'string' ? value : undefined;
|
|
36
36
|
}
|
|
37
37
|
const expressions = common_1.AstNode.readField({ node: property, key: 'expressions' });
|
|
38
38
|
const quasis = common_1.AstNode.readField({ node: property, key: 'quasis' });
|
|
39
|
-
if (common_1.AstNode.getType({ node: property }) ===
|
|
39
|
+
if (common_1.AstNode.getType({ node: property }) === common_1.AstNodeTypes.TEMPLATE_LITERAL &&
|
|
40
40
|
Array.isArray(expressions) &&
|
|
41
41
|
expressions.length === 0 &&
|
|
42
42
|
Array.isArray(quasis)) {
|
|
@@ -54,13 +54,13 @@ class PromiseChainSupport {
|
|
|
54
54
|
*/
|
|
55
55
|
static chainMethodOf(opts) {
|
|
56
56
|
const call = PromiseChainSupport.unwrap({ node: opts.node });
|
|
57
|
-
if (common_1.AstNode.getType({ node: call }) !==
|
|
57
|
+
if (common_1.AstNode.getType({ node: call }) !== common_1.AstNodeTypes.CALL_EXPRESSION) {
|
|
58
58
|
return undefined;
|
|
59
59
|
}
|
|
60
60
|
const callee = PromiseChainSupport.unwrap({
|
|
61
61
|
node: common_1.AstNode.readField({ node: call, key: 'callee' }),
|
|
62
62
|
});
|
|
63
|
-
if (common_1.AstNode.getType({ node: callee }) !==
|
|
63
|
+
if (common_1.AstNode.getType({ node: callee }) !== common_1.AstNodeTypes.MEMBER_EXPRESSION) {
|
|
64
64
|
return undefined;
|
|
65
65
|
}
|
|
66
66
|
const name = PromiseChainSupport.memberName({ member: callee });
|
|
@@ -74,7 +74,7 @@ class PromiseChainSupport {
|
|
|
74
74
|
let current = PromiseChainSupport.unwrap({ node: opts.node });
|
|
75
75
|
for (;;) {
|
|
76
76
|
const type = common_1.AstNode.getType({ node: current });
|
|
77
|
-
if (type ===
|
|
77
|
+
if (type === common_1.AstNodeTypes.CALL_EXPRESSION) {
|
|
78
78
|
if (PromiseChainSupport.chainMethodOf({ node: current }) !== undefined) {
|
|
79
79
|
return true;
|
|
80
80
|
}
|
|
@@ -83,7 +83,7 @@ class PromiseChainSupport {
|
|
|
83
83
|
});
|
|
84
84
|
continue;
|
|
85
85
|
}
|
|
86
|
-
if (type ===
|
|
86
|
+
if (type === common_1.AstNodeTypes.MEMBER_EXPRESSION) {
|
|
87
87
|
current = PromiseChainSupport.unwrap({
|
|
88
88
|
node: common_1.AstNode.readField({ node: current, key: 'object' }),
|
|
89
89
|
});
|
|
@@ -101,29 +101,29 @@ class PromiseChainSupport {
|
|
|
101
101
|
const type = common_1.AstNode.getType({ node }) ?? '';
|
|
102
102
|
const constant = (child) => PromiseChainSupport.isConstant({ node: child });
|
|
103
103
|
switch (type) {
|
|
104
|
-
case
|
|
104
|
+
case common_1.AstNodeTypes.LITERAL: {
|
|
105
105
|
return true;
|
|
106
106
|
}
|
|
107
|
-
case
|
|
107
|
+
case common_1.AstNodeTypes.IDENTIFIER: {
|
|
108
108
|
return common_1.AstNode.readField({ node, key: 'name' }) === 'undefined';
|
|
109
109
|
}
|
|
110
|
-
case
|
|
110
|
+
case common_1.AstNodeTypes.TEMPLATE_LITERAL: {
|
|
111
111
|
const expressions = common_1.AstNode.readField({ node, key: 'expressions' });
|
|
112
112
|
return Array.isArray(expressions) && expressions.length === 0;
|
|
113
113
|
}
|
|
114
|
-
case
|
|
114
|
+
case common_1.AstNodeTypes.UNARY_EXPRESSION: {
|
|
115
115
|
return (CONSTANT_UNARY_OPERATORS.has(String(common_1.AstNode.readField({ node, key: 'operator' }))) &&
|
|
116
116
|
constant(common_1.AstNode.readField({ node, key: 'argument' })));
|
|
117
117
|
}
|
|
118
|
-
case
|
|
118
|
+
case common_1.AstNodeTypes.ARRAY_EXPRESSION: {
|
|
119
119
|
const elements = common_1.AstNode.readField({ node, key: 'elements' });
|
|
120
120
|
return (Array.isArray(elements) &&
|
|
121
121
|
elements.every((element) => element === null || constant(element)));
|
|
122
122
|
}
|
|
123
|
-
case
|
|
123
|
+
case common_1.AstNodeTypes.OBJECT_EXPRESSION: {
|
|
124
124
|
const properties = common_1.AstNode.readField({ node, key: 'properties' });
|
|
125
125
|
return (Array.isArray(properties) &&
|
|
126
|
-
properties.every((property) => common_1.AstNode.getType({ node: property }) ===
|
|
126
|
+
properties.every((property) => common_1.AstNode.getType({ node: property }) === common_1.AstNodeTypes.PROPERTY &&
|
|
127
127
|
common_1.AstNode.readField({ node: property, key: 'computed' }) !== true &&
|
|
128
128
|
common_1.AstNode.readField({ node: property, key: 'method' }) !== true &&
|
|
129
129
|
common_1.AstNode.readField({ node: property, key: 'kind' }) === 'init' &&
|
|
@@ -144,16 +144,16 @@ class PromiseChainSupport {
|
|
|
144
144
|
return (Array.isArray(statements) &&
|
|
145
145
|
statements.every((statement) => {
|
|
146
146
|
const type = common_1.AstNode.getType({ node: statement });
|
|
147
|
-
if (type ===
|
|
147
|
+
if (type === common_1.AstNodeTypes.EMPTY_STATEMENT) {
|
|
148
148
|
return true;
|
|
149
149
|
}
|
|
150
|
-
if (type ===
|
|
150
|
+
if (type === common_1.AstNodeTypes.RETURN_STATEMENT) {
|
|
151
151
|
const argument = common_1.AstNode.readField({ node: statement, key: 'argument' });
|
|
152
152
|
return argument === null || PromiseChainSupport.isConstant({ node: argument });
|
|
153
153
|
}
|
|
154
154
|
const expression = common_1.AstNode.readField({ node: statement, key: 'expression' });
|
|
155
|
-
return (type ===
|
|
156
|
-
common_1.AstNode.getType({ node: expression }) ===
|
|
155
|
+
return (type === common_1.AstNodeTypes.EXPRESSION_STATEMENT &&
|
|
156
|
+
common_1.AstNode.getType({ node: expression }) === common_1.AstNodeTypes.ASSIGNMENT_EXPRESSION &&
|
|
157
157
|
common_1.AstNode.readField({ node: expression, key: 'operator' }) === '=' &&
|
|
158
158
|
PromiseChainSupport.isPlainTarget({
|
|
159
159
|
node: common_1.AstNode.readField({ node: expression, key: 'left' }),
|
|
@@ -167,10 +167,10 @@ class PromiseChainSupport {
|
|
|
167
167
|
static isPlainTarget(opts) {
|
|
168
168
|
const { node } = opts;
|
|
169
169
|
const type = common_1.AstNode.getType({ node });
|
|
170
|
-
if (type ===
|
|
170
|
+
if (type === common_1.AstNodeTypes.IDENTIFIER || type === common_1.AstNodeTypes.THIS_EXPRESSION) {
|
|
171
171
|
return true;
|
|
172
172
|
}
|
|
173
|
-
return (type ===
|
|
173
|
+
return (type === common_1.AstNodeTypes.MEMBER_EXPRESSION &&
|
|
174
174
|
common_1.AstNode.readField({ node, key: 'computed' }) !== true &&
|
|
175
175
|
PromiseChainSupport.isPlainTarget({ node: common_1.AstNode.readField({ node, key: 'object' }) }));
|
|
176
176
|
}
|
|
@@ -178,7 +178,7 @@ class PromiseChainSupport {
|
|
|
178
178
|
static unwrapTypes(opts) {
|
|
179
179
|
let current = opts.node;
|
|
180
180
|
while (VALUE_WRAPPERS.has(common_1.AstNode.getType({ node: current }) ?? '') &&
|
|
181
|
-
common_1.AstNode.getType({ node: current }) !==
|
|
181
|
+
common_1.AstNode.getType({ node: current }) !== common_1.AstNodeTypes.CHAIN_EXPRESSION) {
|
|
182
182
|
current = common_1.AstNode.readField({ node: current, key: 'expression' });
|
|
183
183
|
}
|
|
184
184
|
return current;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"promise-chain-support.js","sourceRoot":"","sources":["../../../src/linters/house/promise-chain-support.ts"],"names":[],"mappings":"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","sourcesContent":["import { AstNode } from './common';\n\nconst CHAIN_METHODS = new Set(['then', 'catch', 'finally']);\n/** Wrappers that leave the value of the expression they hold unchanged: `x!`, `x as T`, `x satisfies T`, `<T>x`, `a?.b`. */\nconst VALUE_WRAPPERS = new Set([\n 'TSAsExpression',\n 'TSSatisfiesExpression',\n 'TSNonNullExpression',\n 'TSTypeAssertion',\n 'ChainExpression',\n]);\nconst CONSTANT_UNARY_OPERATORS = new Set(['-', '+', '!', 'void']);\n\n/** The shared parts of the promise chain rules: what a chain call is, what a constant is, what a silent handler body is. */\nexport class PromiseChainSupport {\n /** `node` without the wrappers that do not change its value (`!`, `as`, `satisfies`, `<T>`, an optional chain). */\n static unwrap(opts: { node: unknown }): unknown {\n let current = opts.node;\n\n while (VALUE_WRAPPERS.has(AstNode.getType({ node: current }) ?? '')) {\n current = AstNode.readField({ node: current, key: 'expression' });\n }\n\n return current;\n }\n\n /** The name a member access reads: `a.name`, `a['name']`, ``a[`name`]``; `undefined` for a computed key. */\n static memberName(opts: { member: unknown }): string | undefined {\n const { member } = opts;\n const property = AstNode.readField({ node: member, key: 'property' });\n\n if (AstNode.readField({ node: member, key: 'computed' }) !== true) {\n const name = AstNode.readField({ node: property, key: 'name' });\n\n return typeof name === 'string' ? name : undefined;\n }\n\n if (AstNode.getType({ node: property }) === 'Literal') {\n const value = AstNode.readField({ node: property, key: 'value' });\n\n return typeof value === 'string' ? value : undefined;\n }\n\n const expressions = AstNode.readField({ node: property, key: 'expressions' });\n const quasis = AstNode.readField({ node: property, key: 'quasis' });\n\n if (\n AstNode.getType({ node: property }) === 'TemplateLiteral' &&\n Array.isArray(expressions) &&\n expressions.length === 0 &&\n Array.isArray(quasis)\n ) {\n const cooked = AstNode.readField({\n node: AstNode.readField({ node: quasis[0], key: 'value' }),\n key: 'cooked',\n });\n\n return typeof cooked === 'string' ? cooked : undefined;\n }\n\n return undefined;\n }\n\n /**\n * `then`, `catch` or `finally` when `node` (after `unwrap`) is a call of that method - `p.then(f)`, `p?.catch(f)`,\n * `p['finally'](f)` - and `undefined` for anything else. It reads the syntax only, so a thenable counts too.\n */\n static chainMethodOf(opts: { node: unknown }): string | undefined {\n const call = PromiseChainSupport.unwrap({ node: opts.node });\n\n if (AstNode.getType({ node: call }) !== 'CallExpression') {\n return undefined;\n }\n\n const callee = PromiseChainSupport.unwrap({\n node: AstNode.readField({ node: call, key: 'callee' }),\n });\n\n if (AstNode.getType({ node: callee }) !== 'MemberExpression') {\n return undefined;\n }\n\n const name = PromiseChainSupport.memberName({ member: callee });\n\n return name !== undefined && CHAIN_METHODS.has(name) ? name : undefined;\n }\n\n /**\n * Whether a chain call (`.then`, `.catch`, `.finally`) sits anywhere on the spine of `node`: the receivers and\n * callees a call chain is built from (`a.then(f).limit(1)` has one, `a.where(x).limit(1)` has none).\n */\n static hasChainOnSpine(opts: { node: unknown }): boolean {\n let current = PromiseChainSupport.unwrap({ node: opts.node });\n\n for (;;) {\n const type = AstNode.getType({ node: current });\n\n if (type === 'CallExpression') {\n if (PromiseChainSupport.chainMethodOf({ node: current }) !== undefined) {\n return true;\n }\n\n current = PromiseChainSupport.unwrap({\n node: AstNode.readField({ node: current, key: 'callee' }),\n });\n continue;\n }\n\n if (type === 'MemberExpression') {\n current = PromiseChainSupport.unwrap({\n node: AstNode.readField({ node: current, key: 'object' }),\n });\n continue;\n }\n\n return false;\n }\n }\n\n /**\n * A value that is the same every time and reads nothing: a literal, `undefined`, a template with no `${}`, `-1`,\n * `void 0`, and an array or object literal built only from those (`[]`, `{}`, `{ items: [] }`).\n */\n static isConstant(opts: { node: unknown }): boolean {\n const node = PromiseChainSupport.unwrapTypes({ node: opts.node });\n const type = AstNode.getType({ node }) ?? '';\n const constant = (child: unknown) => PromiseChainSupport.isConstant({ node: child });\n\n switch (type) {\n case 'Literal': {\n return true;\n }\n case 'Identifier': {\n return AstNode.readField({ node, key: 'name' }) === 'undefined';\n }\n case 'TemplateLiteral': {\n const expressions = AstNode.readField({ node, key: 'expressions' });\n\n return Array.isArray(expressions) && expressions.length === 0;\n }\n case 'UnaryExpression': {\n return (\n CONSTANT_UNARY_OPERATORS.has(String(AstNode.readField({ node, key: 'operator' }))) &&\n constant(AstNode.readField({ node, key: 'argument' }))\n );\n }\n case 'ArrayExpression': {\n const elements = AstNode.readField({ node, key: 'elements' });\n\n return (\n Array.isArray(elements) &&\n elements.every((element) => element === null || constant(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 constant(AstNode.readField({ node: property, key: 'value' })),\n )\n );\n }\n default: {\n return false;\n }\n }\n }\n\n /**\n * Whether the statements of a handler or a `catch` block leave no trace of the error: none at all (a comment does\n * not count), or only `return;`, `return <constant>;` and `<name or member> = <constant>;`. Anything else - a\n * call, a `throw`, a read of a variable - is a decision someone made, and counts as handled.\n */\n static isSilentBlock(opts: { statements: unknown }): boolean {\n const { statements } = opts;\n\n return (\n Array.isArray(statements) &&\n statements.every((statement) => {\n const type = AstNode.getType({ node: statement });\n\n if (type === 'EmptyStatement') {\n return true;\n }\n\n if (type === 'ReturnStatement') {\n const argument = AstNode.readField({ node: statement, key: 'argument' });\n\n return argument === null || PromiseChainSupport.isConstant({ node: argument });\n }\n\n const expression = AstNode.readField({ node: statement, key: 'expression' });\n\n return (\n type === 'ExpressionStatement' &&\n AstNode.getType({ node: expression }) === 'AssignmentExpression' &&\n AstNode.readField({ node: expression, key: 'operator' }) === '=' &&\n PromiseChainSupport.isPlainTarget({\n node: AstNode.readField({ node: expression, key: 'left' }),\n }) &&\n PromiseChainSupport.isConstant({\n node: AstNode.readField({ node: expression, key: 'right' }),\n })\n );\n })\n );\n }\n\n /** `name`, `this.name`, `a.b.c`: an assignment target that reads no computed key and calls nothing. */\n static isPlainTarget(opts: { node: unknown }): boolean {\n const { node } = opts;\n const type = AstNode.getType({ node });\n\n if (type === 'Identifier' || type === 'ThisExpression') {\n return true;\n }\n\n return (\n type === 'MemberExpression' &&\n AstNode.readField({ node, key: 'computed' }) !== true &&\n PromiseChainSupport.isPlainTarget({ node: AstNode.readField({ node, key: 'object' }) })\n );\n }\n\n /** `node` without the type-only wrappers (`as`, `satisfies`, `!`, `<T>`), keeping an optional chain. */\n static unwrapTypes(opts: { node: unknown }): unknown {\n let current = opts.node;\n\n while (\n VALUE_WRAPPERS.has(AstNode.getType({ node: current }) ?? '') &&\n AstNode.getType({ node: current }) !== 'ChainExpression'\n ) {\n current = AstNode.readField({ node: current, key: 'expression' });\n }\n\n return current;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"promise-chain-support.js","sourceRoot":"","sources":["../../../src/linters/house/promise-chain-support.ts"],"names":[],"mappings":"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","sourcesContent":["import { AstNode, AstNodeTypes } from './common';\n\nconst CHAIN_METHODS = new Set(['then', 'catch', 'finally']);\n/** Wrappers that leave the value of the expression they hold unchanged: `x!`, `x as T`, `x satisfies T`, `<T>x`, `a?.b`. */\nconst VALUE_WRAPPERS = new Set([\n AstNodeTypes.AS_EXPRESSION,\n AstNodeTypes.SATISFIES_EXPRESSION,\n AstNodeTypes.NON_NULL_EXPRESSION,\n AstNodeTypes.TYPE_ASSERTION,\n AstNodeTypes.CHAIN_EXPRESSION,\n]);\nconst CONSTANT_UNARY_OPERATORS = new Set(['-', '+', '!', 'void']);\n\n/** The shared parts of the promise chain rules: what a chain call is, what a constant is, what a silent handler body is. */\nexport class PromiseChainSupport {\n /** `node` without the wrappers that do not change its value (`!`, `as`, `satisfies`, `<T>`, an optional chain). */\n static unwrap(opts: { node: unknown }): unknown {\n let current = opts.node;\n\n while (VALUE_WRAPPERS.has(AstNode.getType({ node: current }) ?? '')) {\n current = AstNode.readField({ node: current, key: 'expression' });\n }\n\n return current;\n }\n\n /** The name a member access reads: `a.name`, `a['name']`, ``a[`name`]``; `undefined` for a computed key. */\n static memberName(opts: { member: unknown }): string | undefined {\n const { member } = opts;\n const property = AstNode.readField({ node: member, key: 'property' });\n\n if (AstNode.readField({ node: member, key: 'computed' }) !== true) {\n const name = AstNode.readField({ node: property, key: 'name' });\n\n return typeof name === 'string' ? name : undefined;\n }\n\n if (AstNode.getType({ node: property }) === AstNodeTypes.LITERAL) {\n const value = AstNode.readField({ node: property, key: 'value' });\n\n return typeof value === 'string' ? value : undefined;\n }\n\n const expressions = AstNode.readField({ node: property, key: 'expressions' });\n const quasis = AstNode.readField({ node: property, key: 'quasis' });\n\n if (\n AstNode.getType({ node: property }) === AstNodeTypes.TEMPLATE_LITERAL &&\n Array.isArray(expressions) &&\n expressions.length === 0 &&\n Array.isArray(quasis)\n ) {\n const cooked = AstNode.readField({\n node: AstNode.readField({ node: quasis[0], key: 'value' }),\n key: 'cooked',\n });\n\n return typeof cooked === 'string' ? cooked : undefined;\n }\n\n return undefined;\n }\n\n /**\n * `then`, `catch` or `finally` when `node` (after `unwrap`) is a call of that method - `p.then(f)`, `p?.catch(f)`,\n * `p['finally'](f)` - and `undefined` for anything else. It reads the syntax only, so a thenable counts too.\n */\n static chainMethodOf(opts: { node: unknown }): string | undefined {\n const call = PromiseChainSupport.unwrap({ node: opts.node });\n\n if (AstNode.getType({ node: call }) !== AstNodeTypes.CALL_EXPRESSION) {\n return undefined;\n }\n\n const callee = PromiseChainSupport.unwrap({\n node: AstNode.readField({ node: call, key: 'callee' }),\n });\n\n if (AstNode.getType({ node: callee }) !== AstNodeTypes.MEMBER_EXPRESSION) {\n return undefined;\n }\n\n const name = PromiseChainSupport.memberName({ member: callee });\n\n return name !== undefined && CHAIN_METHODS.has(name) ? name : undefined;\n }\n\n /**\n * Whether a chain call (`.then`, `.catch`, `.finally`) sits anywhere on the spine of `node`: the receivers and\n * callees a call chain is built from (`a.then(f).limit(1)` has one, `a.where(x).limit(1)` has none).\n */\n static hasChainOnSpine(opts: { node: unknown }): boolean {\n let current = PromiseChainSupport.unwrap({ node: opts.node });\n\n for (;;) {\n const type = AstNode.getType({ node: current });\n\n if (type === AstNodeTypes.CALL_EXPRESSION) {\n if (PromiseChainSupport.chainMethodOf({ node: current }) !== undefined) {\n return true;\n }\n\n current = PromiseChainSupport.unwrap({\n node: AstNode.readField({ node: current, key: 'callee' }),\n });\n continue;\n }\n\n if (type === AstNodeTypes.MEMBER_EXPRESSION) {\n current = PromiseChainSupport.unwrap({\n node: AstNode.readField({ node: current, key: 'object' }),\n });\n continue;\n }\n\n return false;\n }\n }\n\n /**\n * A value that is the same every time and reads nothing: a literal, `undefined`, a template with no `${}`, `-1`,\n * `void 0`, and an array or object literal built only from those (`[]`, `{}`, `{ items: [] }`).\n */\n static isConstant(opts: { node: unknown }): boolean {\n const node = PromiseChainSupport.unwrapTypes({ node: opts.node });\n const type = AstNode.getType({ node }) ?? '';\n const constant = (child: unknown) => PromiseChainSupport.isConstant({ node: child });\n\n switch (type) {\n case AstNodeTypes.LITERAL: {\n return true;\n }\n case AstNodeTypes.IDENTIFIER: {\n return AstNode.readField({ node, key: 'name' }) === 'undefined';\n }\n case AstNodeTypes.TEMPLATE_LITERAL: {\n const expressions = AstNode.readField({ node, key: 'expressions' });\n\n return Array.isArray(expressions) && expressions.length === 0;\n }\n case AstNodeTypes.UNARY_EXPRESSION: {\n return (\n CONSTANT_UNARY_OPERATORS.has(String(AstNode.readField({ node, key: 'operator' }))) &&\n constant(AstNode.readField({ node, key: 'argument' }))\n );\n }\n case AstNodeTypes.ARRAY_EXPRESSION: {\n const elements = AstNode.readField({ node, key: 'elements' });\n\n return (\n Array.isArray(elements) &&\n elements.every((element) => element === null || constant(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 constant(AstNode.readField({ node: property, key: 'value' })),\n )\n );\n }\n default: {\n return false;\n }\n }\n }\n\n /**\n * Whether the statements of a handler or a `catch` block leave no trace of the error: none at all (a comment does\n * not count), or only `return;`, `return <constant>;` and `<name or member> = <constant>;`. Anything else - a\n * call, a `throw`, a read of a variable - is a decision someone made, and counts as handled.\n */\n static isSilentBlock(opts: { statements: unknown }): boolean {\n const { statements } = opts;\n\n return (\n Array.isArray(statements) &&\n statements.every((statement) => {\n const type = AstNode.getType({ node: statement });\n\n if (type === AstNodeTypes.EMPTY_STATEMENT) {\n return true;\n }\n\n if (type === AstNodeTypes.RETURN_STATEMENT) {\n const argument = AstNode.readField({ node: statement, key: 'argument' });\n\n return argument === null || PromiseChainSupport.isConstant({ node: argument });\n }\n\n const expression = AstNode.readField({ node: statement, key: 'expression' });\n\n return (\n type === AstNodeTypes.EXPRESSION_STATEMENT &&\n AstNode.getType({ node: expression }) === AstNodeTypes.ASSIGNMENT_EXPRESSION &&\n AstNode.readField({ node: expression, key: 'operator' }) === '=' &&\n PromiseChainSupport.isPlainTarget({\n node: AstNode.readField({ node: expression, key: 'left' }),\n }) &&\n PromiseChainSupport.isConstant({\n node: AstNode.readField({ node: expression, key: 'right' }),\n })\n );\n })\n );\n }\n\n /** `name`, `this.name`, `a.b.c`: an assignment target that reads no computed key and calls nothing. */\n static isPlainTarget(opts: { node: unknown }): boolean {\n const { node } = opts;\n const type = AstNode.getType({ node });\n\n if (type === AstNodeTypes.IDENTIFIER || type === AstNodeTypes.THIS_EXPRESSION) {\n return true;\n }\n\n return (\n type === AstNodeTypes.MEMBER_EXPRESSION &&\n AstNode.readField({ node, key: 'computed' }) !== true &&\n PromiseChainSupport.isPlainTarget({ node: AstNode.readField({ node, key: 'object' }) })\n );\n }\n\n /** `node` without the type-only wrappers (`as`, `satisfies`, `!`, `<T>`), keeping an optional chain. */\n static unwrapTypes(opts: { node: unknown }): unknown {\n let current = opts.node;\n\n while (\n VALUE_WRAPPERS.has(AstNode.getType({ node: current }) ?? '') &&\n AstNode.getType({ node: current }) !== AstNodeTypes.CHAIN_EXPRESSION\n ) {\n current = AstNode.readField({ node: current, key: 'expression' });\n }\n\n return current;\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@venizia/dev-configs",
|
|
3
|
-
"version": "0.4.8-
|
|
3
|
+
"version": "0.4.8-4",
|
|
4
4
|
"description": "Shareable development configurations for TypeScript projects: oxlint presets with per-rule builders, the ESLint naming-convention rule, the legacy ESLint flat config, and TypeScript compiler options with critical decorator support (experimentalDecorators, emitDecoratorMetadata, useDefineForClassFields). Single source of truth for consistent code style, type checking, and build settings across monorepo packages.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"build-tools",
|