@venizia/dev-configs 0.4.6 → 0.4.7-1
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/LICENSE.md +1 -3
- package/README.md +1 -1
- package/dist/checks/catalog.d.ts +4 -2
- package/dist/checks/catalog.d.ts.map +1 -1
- package/dist/checks/catalog.js +72 -68
- package/dist/checks/catalog.js.map +1 -1
- package/dist/checks/module-cycles.d.ts +11 -9
- package/dist/checks/module-cycles.d.ts.map +1 -1
- package/dist/checks/module-cycles.js +32 -30
- package/dist/checks/module-cycles.js.map +1 -1
- package/dist/checks/purity/manifest.d.ts +44 -38
- package/dist/checks/purity/manifest.d.ts.map +1 -1
- package/dist/checks/purity/manifest.js +121 -115
- package/dist/checks/purity/manifest.js.map +1 -1
- package/dist/checks/purity/probe.d.ts +22 -18
- package/dist/checks/purity/probe.d.ts.map +1 -1
- package/dist/checks/purity/probe.js +101 -99
- package/dist/checks/purity/probe.js.map +1 -1
- package/dist/checks/purity/run.d.ts +18 -16
- package/dist/checks/purity/run.d.ts.map +1 -1
- package/dist/checks/purity/run.js +90 -86
- package/dist/checks/purity/run.js.map +1 -1
- package/dist/checks/test-controls.d.ts +17 -15
- package/dist/checks/test-controls.d.ts.map +1 -1
- package/dist/checks/test-controls.js +71 -69
- package/dist/checks/test-controls.js.map +1 -1
- package/dist/checks/test-dead-code.d.ts +5 -3
- package/dist/checks/test-dead-code.d.ts.map +1 -1
- package/dist/checks/test-dead-code.js +23 -21
- package/dist/checks/test-dead-code.js.map +1 -1
- package/dist/checks/test-mutate.d.ts +12 -7
- package/dist/checks/test-mutate.d.ts.map +1 -1
- package/dist/checks/test-mutate.js +59 -56
- package/dist/checks/test-mutate.js.map +1 -1
- package/dist/checks/test-weight.d.ts +11 -8
- package/dist/checks/test-weight.d.ts.map +1 -1
- package/dist/checks/test-weight.js +98 -94
- package/dist/checks/test-weight.js.map +1 -1
- package/dist/cli/check.d.ts.map +1 -1
- package/dist/cli/check.js +11 -8
- package/dist/cli/check.js.map +1 -1
- package/dist/cli/codemod/async-style.d.ts +62 -0
- package/dist/cli/codemod/async-style.d.ts.map +1 -0
- package/dist/cli/codemod/async-style.js +248 -0
- package/dist/cli/codemod/async-style.js.map +1 -0
- package/dist/cli/codemod/const-classes.d.ts.map +1 -1
- package/dist/cli/codemod/const-classes.js +2 -1
- package/dist/cli/codemod/const-classes.js.map +1 -1
- package/dist/cli/codemod/drop-redundant-casts.d.ts.map +1 -1
- package/dist/cli/codemod/drop-redundant-casts.js +2 -1
- package/dist/cli/codemod/drop-redundant-casts.js.map +1 -1
- package/dist/cli/codemod/files.d.ts +7 -0
- package/dist/cli/codemod/files.d.ts.map +1 -1
- package/dist/cli/codemod/files.js +33 -0
- package/dist/cli/codemod/files.js.map +1 -1
- package/dist/cli/codemod/index.d.ts.map +1 -1
- package/dist/cli/codemod/index.js +12 -3
- package/dist/cli/codemod/index.js.map +1 -1
- package/dist/cli/codemod/model-settings.d.ts +7 -5
- package/dist/cli/codemod/model-settings.d.ts.map +1 -1
- package/dist/cli/codemod/model-settings.js +293 -291
- package/dist/cli/codemod/model-settings.js.map +1 -1
- package/dist/cli/codemod/namespace-functions/index.d.ts +20 -0
- package/dist/cli/codemod/namespace-functions/index.d.ts.map +1 -0
- package/dist/cli/codemod/namespace-functions/index.js +182 -0
- package/dist/cli/codemod/namespace-functions/index.js.map +1 -0
- package/dist/cli/codemod/namespace-functions/logger-scope.d.ts +32 -0
- package/dist/cli/codemod/namespace-functions/logger-scope.d.ts.map +1 -0
- package/dist/cli/codemod/namespace-functions/logger-scope.js +128 -0
- package/dist/cli/codemod/namespace-functions/logger-scope.js.map +1 -0
- package/dist/cli/codemod/namespace-functions/mapping.d.ts +66 -0
- package/dist/cli/codemod/namespace-functions/mapping.d.ts.map +1 -0
- package/dist/cli/codemod/namespace-functions/mapping.js +99 -0
- package/dist/cli/codemod/namespace-functions/mapping.js.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/boot.d.ts +7 -0
- package/dist/cli/codemod/namespace-functions/mappings/boot.d.ts.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/boot.js +28 -0
- package/dist/cli/codemod/namespace-functions/mappings/boot.js.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/connectors.d.ts +4 -0
- package/dist/cli/codemod/namespace-functions/mappings/connectors.d.ts.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/connectors.js +218 -0
- package/dist/cli/codemod/namespace-functions/mappings/connectors.js.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/core-server.d.ts +7 -0
- package/dist/cli/codemod/namespace-functions/mappings/core-server.d.ts.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/core-server.js +162 -0
- package/dist/cli/codemod/namespace-functions/mappings/core-server.js.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/core-worker.d.ts +7 -0
- package/dist/cli/codemod/namespace-functions/mappings/core-worker.d.ts.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/core-worker.js +18 -0
- package/dist/cli/codemod/namespace-functions/mappings/core-worker.js.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/dev-configs.d.ts +7 -0
- package/dist/cli/codemod/namespace-functions/mappings/dev-configs.d.ts.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/dev-configs.js +192 -0
- package/dist/cli/codemod/namespace-functions/mappings/dev-configs.js.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/filter.d.ts +7 -0
- package/dist/cli/codemod/namespace-functions/mappings/filter.d.ts.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/filter.js +30 -0
- package/dist/cli/codemod/namespace-functions/mappings/filter.js.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/helpers.d.ts +16 -0
- package/dist/cli/codemod/namespace-functions/mappings/helpers.d.ts.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/helpers.js +535 -0
- package/dist/cli/codemod/namespace-functions/mappings/helpers.js.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/index.d.ts +4 -0
- package/dist/cli/codemod/namespace-functions/mappings/index.d.ts.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/index.js +25 -0
- package/dist/cli/codemod/namespace-functions/mappings/index.js.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/inversion.d.ts +10 -0
- package/dist/cli/codemod/namespace-functions/mappings/inversion.d.ts.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/inversion.js +81 -0
- package/dist/cli/codemod/namespace-functions/mappings/inversion.js.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/kernel.d.ts +17 -0
- package/dist/cli/codemod/namespace-functions/mappings/kernel.d.ts.map +1 -0
- package/dist/cli/codemod/namespace-functions/mappings/kernel.js +229 -0
- package/dist/cli/codemod/namespace-functions/mappings/kernel.js.map +1 -0
- package/dist/cli/codemod/namespace-functions/rewriter.d.ts +61 -0
- package/dist/cli/codemod/namespace-functions/rewriter.d.ts.map +1 -0
- package/dist/cli/codemod/namespace-functions/rewriter.js +564 -0
- package/dist/cli/codemod/namespace-functions/rewriter.js.map +1 -0
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/compilers/bun.d.ts +1 -1
- package/dist/compilers/bun.js +1 -1
- package/dist/compilers/bun.js.map +1 -1
- package/dist/linters/house/await-support.d.ts +74 -0
- package/dist/linters/house/await-support.d.ts.map +1 -0
- package/dist/linters/house/await-support.js +238 -0
- package/dist/linters/house/await-support.js.map +1 -0
- package/dist/linters/house/common.d.ts +15 -9
- package/dist/linters/house/common.d.ts.map +1 -1
- package/dist/linters/house/common.js +20 -15
- package/dist/linters/house/common.js.map +1 -1
- package/dist/linters/house/configs.d.ts +26 -0
- package/dist/linters/house/configs.d.ts.map +1 -1
- package/dist/linters/house/configs.js +55 -1
- package/dist/linters/house/configs.js.map +1 -1
- package/dist/linters/house/const-class-values.rule.d.ts.map +1 -1
- package/dist/linters/house/const-class-values.rule.js +27 -19
- package/dist/linters/house/const-class-values.rule.js.map +1 -1
- package/dist/linters/house/effect-cleanup-consistency.rule.d.ts +17 -0
- package/dist/linters/house/effect-cleanup-consistency.rule.d.ts.map +1 -0
- package/dist/linters/house/effect-cleanup-consistency.rule.js +87 -0
- package/dist/linters/house/effect-cleanup-consistency.rule.js.map +1 -0
- package/dist/linters/house/hook-support.d.ts +29 -0
- package/dist/linters/house/hook-support.d.ts.map +1 -0
- package/dist/linters/house/hook-support.js +72 -0
- package/dist/linters/house/hook-support.js.map +1 -0
- package/dist/linters/house/index.d.ts +9 -0
- package/dist/linters/house/index.d.ts.map +1 -1
- package/dist/linters/house/index.js +9 -0
- package/dist/linters/house/index.js.map +1 -1
- package/dist/linters/house/max-params-own.rule.d.ts.map +1 -1
- package/dist/linters/house/max-params-own.rule.js +33 -24
- package/dist/linters/house/max-params-own.rule.js.map +1 -1
- package/dist/linters/house/no-async-hook-callback.rule.d.ts +18 -0
- package/dist/linters/house/no-async-hook-callback.rule.d.ts.map +1 -0
- package/dist/linters/house/no-async-hook-callback.rule.js +50 -0
- package/dist/linters/house/no-async-hook-callback.rule.js.map +1 -0
- package/dist/linters/house/no-await-promise-chain.rule.d.ts +24 -0
- package/dist/linters/house/no-await-promise-chain.rule.d.ts.map +1 -0
- package/dist/linters/house/no-await-promise-chain.rule.js +298 -0
- package/dist/linters/house/no-await-promise-chain.rule.js.map +1 -0
- package/dist/linters/house/no-inline-await.rule.d.ts +20 -0
- package/dist/linters/house/no-inline-await.rule.d.ts.map +1 -0
- package/dist/linters/house/no-inline-await.rule.js +70 -0
- package/dist/linters/house/no-inline-await.rule.js.map +1 -0
- package/dist/linters/house/no-new-error.rule.js +4 -4
- package/dist/linters/house/no-new-error.rule.js.map +1 -1
- package/dist/linters/house/no-return-await.rule.d.ts +15 -0
- package/dist/linters/house/no-return-await.rule.d.ts.map +1 -0
- package/dist/linters/house/no-return-await.rule.js +92 -0
- package/dist/linters/house/no-return-await.rule.js.map +1 -0
- package/dist/linters/house/no-silent-catch.rule.d.ts +22 -0
- package/dist/linters/house/no-silent-catch.rule.d.ts.map +1 -0
- package/dist/linters/house/no-silent-catch.rule.js +88 -0
- package/dist/linters/house/no-silent-catch.rule.js.map +1 -0
- package/dist/linters/house/plugin.d.ts.map +1 -1
- package/dist/linters/house/plugin.js +12 -0
- package/dist/linters/house/plugin.js.map +1 -1
- package/dist/linters/house/promise-chain-support.d.ts +49 -0
- package/dist/linters/house/promise-chain-support.d.ts.map +1 -0
- package/dist/linters/house/promise-chain-support.js +188 -0
- package/dist/linters/house/promise-chain-support.js.map +1 -0
- package/dist/linters/rules/no-restricted-properties.rule.js +1 -1
- package/dist/linters/rules/no-restricted-properties.rule.js.map +1 -1
- package/dist/testing/rejection.helper.d.ts +25 -20
- package/dist/testing/rejection.helper.d.ts.map +1 -1
- package/dist/testing/rejection.helper.js +33 -31
- package/dist/testing/rejection.helper.js.map +1 -1
- package/dist/testing/repo-tmp.d.ts +19 -9
- package/dist/testing/repo-tmp.d.ts.map +1 -1
- package/dist/testing/repo-tmp.js +50 -48
- package/dist/testing/repo-tmp.js.map +1 -1
- package/dist/testing/spawn.helper.d.ts +12 -10
- package/dist/testing/spawn.helper.d.ts.map +1 -1
- package/dist/testing/spawn.helper.js +22 -16
- package/dist/testing/spawn.helper.js.map +1 -1
- package/dist/testing/tmpdir-preload.js +1 -1
- package/dist/testing/tmpdir-preload.js.map +1 -1
- package/package.json +2 -3
|
@@ -0,0 +1 @@
|
|
|
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 } from './await-support';\nimport { AstNode, AstNodeTypes, HOUSE_PLUGIN_NAMESPACE } from './common';\n\nconst FUNCTION_TYPES = new Set([\n 'FunctionDeclaration',\n 'FunctionExpression',\n 'ArrowFunctionExpression',\n]);\nconst STATEMENT_LISTS = new Set(['BlockStatement', 'Program', 'StaticBlock', 'SwitchCase']);\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 }) === 'TryStatement') {\n return true;\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 }) !== 'SequenceExpression'\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 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 if (\n AwaitSupport.isNode(argument) &&\n AstNode.getType({ node: argument }) === 'AwaitExpression'\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 if (AwaitSupport.isNode(body) && AstNode.getType({ node: body }) === 'AwaitExpression') {\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"]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Rule } from 'eslint';
|
|
2
|
+
import type { TRuleSeverity } from '../rules/common';
|
|
3
|
+
/**
|
|
4
|
+
* `venizia/no-silent-catch`. A handled error leaves a trace (V-C-06). Reported: a `.catch(h)` (also `?.catch`,
|
|
5
|
+
* `['catch']`) whose handler is an arrow or function expression that ignores its parameter and whose body is empty
|
|
6
|
+
* or only gives back a constant (`() => null`, `() => undefined`, `() => ({})`, `() => []`, `() => {}`,
|
|
7
|
+
* `function () {}`), and a `catch` block that is empty, holds only a comment, or only assigns or returns a constant
|
|
8
|
+
* without reading the error. Handled, and not reported: anything that reads the error (logs, wraps or rethrows
|
|
9
|
+
* it), makes any call (a log, a cleanup, a fallback), throws, or reads another variable.
|
|
10
|
+
*
|
|
11
|
+
* It is not ESLint's `no-empty`: `no-empty` reports an empty block only, lets a block that holds a comment pass,
|
|
12
|
+
* and never sees `.catch(() => null)`. Both report `catch {}`, each with its own message. There is no fix: what to
|
|
13
|
+
* log is a decision. A deliberate silent catch carries an `eslint-disable-next-line` with its reason.
|
|
14
|
+
*/
|
|
15
|
+
export declare class NoSilentCatchRule {
|
|
16
|
+
static readonly NAME = "venizia/no-silent-catch";
|
|
17
|
+
static readonly RULE: Rule.RuleModule;
|
|
18
|
+
static build(opts?: {
|
|
19
|
+
severity?: TRuleSeverity;
|
|
20
|
+
}): TRuleSeverity;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=no-silent-catch.rule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-silent-catch.rule.d.ts","sourceRoot":"","sources":["../../../src/linters/house/no-silent-catch.rule.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,QAAQ,CAAC;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAsBrD;;;;;;;;;;;GAWG;AACH,qBAAa,iBAAiB;IAC5B,MAAM,CAAC,QAAQ,CAAC,IAAI,6BAA+C;IAEnE,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,UAAU,CAsEnC;IAEF,MAAM,CAAC,KAAK,CAAC,IAAI,GAAE;QAAE,QAAQ,CAAC,EAAE,aAAa,CAAA;KAAO,GAAG,aAAa;CAGrE"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NoSilentCatchRule = void 0;
|
|
4
|
+
const await_support_1 = require("./await-support");
|
|
5
|
+
const common_1 = require("./common");
|
|
6
|
+
const promise_chain_support_1 = require("./promise-chain-support");
|
|
7
|
+
/** Whether a parameter of `owner` (a function or a catch clause) is read or written anywhere. */
|
|
8
|
+
const isParameterUsed = (opts) => opts.sourceCode
|
|
9
|
+
.getDeclaredVariables(opts.owner)
|
|
10
|
+
.some((variable) => variable.defs.some((definition) => ['Parameter', 'CatchClause'].includes(definition.type)) && variable.references.length > 0);
|
|
11
|
+
/** A parameter that is not a plain name (`({ message }) =>`, `catch ({ message })`) reads the error by itself. */
|
|
12
|
+
const isPlainParameter = (opts) => opts.parameter === null ||
|
|
13
|
+
opts.parameter === undefined ||
|
|
14
|
+
common_1.AstNode.getType({ node: opts.parameter }) === 'Identifier';
|
|
15
|
+
/**
|
|
16
|
+
* `venizia/no-silent-catch`. A handled error leaves a trace (V-C-06). Reported: a `.catch(h)` (also `?.catch`,
|
|
17
|
+
* `['catch']`) whose handler is an arrow or function expression that ignores its parameter and whose body is empty
|
|
18
|
+
* or only gives back a constant (`() => null`, `() => undefined`, `() => ({})`, `() => []`, `() => {}`,
|
|
19
|
+
* `function () {}`), and a `catch` block that is empty, holds only a comment, or only assigns or returns a constant
|
|
20
|
+
* without reading the error. Handled, and not reported: anything that reads the error (logs, wraps or rethrows
|
|
21
|
+
* it), makes any call (a log, a cleanup, a fallback), throws, or reads another variable.
|
|
22
|
+
*
|
|
23
|
+
* It is not ESLint's `no-empty`: `no-empty` reports an empty block only, lets a block that holds a comment pass,
|
|
24
|
+
* and never sees `.catch(() => null)`. Both report `catch {}`, each with its own message. There is no fix: what to
|
|
25
|
+
* log is a decision. A deliberate silent catch carries an `eslint-disable-next-line` with its reason.
|
|
26
|
+
*/
|
|
27
|
+
class NoSilentCatchRule {
|
|
28
|
+
static { this.NAME = `${common_1.HOUSE_PLUGIN_NAMESPACE}/no-silent-catch`; }
|
|
29
|
+
static { this.RULE = {
|
|
30
|
+
meta: {
|
|
31
|
+
type: 'suggestion',
|
|
32
|
+
schema: [],
|
|
33
|
+
messages: {
|
|
34
|
+
silentHandler: '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.',
|
|
35
|
+
silentBlock: '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.',
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
create: (context) => {
|
|
39
|
+
const { sourceCode } = context;
|
|
40
|
+
return {
|
|
41
|
+
[common_1.AstNodeTypes.CALL_EXPRESSION]: (node) => {
|
|
42
|
+
if (promise_chain_support_1.PromiseChainSupport.chainMethodOf({ node }) !== 'catch') {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const args = common_1.AstNode.readField({ node, key: 'arguments' });
|
|
46
|
+
const handler = Array.isArray(args) ? args[0] : undefined;
|
|
47
|
+
const handlerType = common_1.AstNode.getType({ node: handler });
|
|
48
|
+
if (!await_support_1.AwaitSupport.isNode(handler) ||
|
|
49
|
+
(handlerType !== 'ArrowFunctionExpression' && handlerType !== 'FunctionExpression')) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const params = common_1.AstNode.readField({ node: handler, key: 'params' });
|
|
53
|
+
if (!Array.isArray(params) ||
|
|
54
|
+
!params.every((parameter) => isPlainParameter({ parameter })) ||
|
|
55
|
+
isParameterUsed({ owner: handler, sourceCode })) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const body = common_1.AstNode.readField({ node: handler, key: 'body' });
|
|
59
|
+
const isSilent = common_1.AstNode.getType({ node: body }) === 'BlockStatement'
|
|
60
|
+
? promise_chain_support_1.PromiseChainSupport.isSilentBlock({
|
|
61
|
+
statements: common_1.AstNode.readField({ node: body, key: 'body' }),
|
|
62
|
+
})
|
|
63
|
+
: promise_chain_support_1.PromiseChainSupport.isConstant({ node: body });
|
|
64
|
+
if (isSilent) {
|
|
65
|
+
context.report({ node: handler, messageId: 'silentHandler' });
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
[common_1.AstNodeTypes.CATCH_CLAUSE]: (node) => {
|
|
69
|
+
if (!isPlainParameter({ parameter: common_1.AstNode.readField({ node, key: 'param' }) }) ||
|
|
70
|
+
isParameterUsed({ owner: node, sourceCode })) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const body = common_1.AstNode.readField({ node, key: 'body' });
|
|
74
|
+
if (promise_chain_support_1.PromiseChainSupport.isSilentBlock({
|
|
75
|
+
statements: common_1.AstNode.readField({ node: body, key: 'body' }),
|
|
76
|
+
})) {
|
|
77
|
+
context.report({ node, messageId: 'silentBlock' });
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
},
|
|
82
|
+
}; }
|
|
83
|
+
static build(opts = {}) {
|
|
84
|
+
return opts.severity ?? 'error';
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
exports.NoSilentCatchRule = NoSilentCatchRule;
|
|
88
|
+
//# sourceMappingURL=no-silent-catch.rule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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', 'CatchClause'].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 }) === '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 if (\n !AwaitSupport.isNode(handler) ||\n (handlerType !== 'ArrowFunctionExpression' && handlerType !== 'FunctionExpression')\n ) {\n return;\n }\n\n const params = AstNode.readField({ node: handler, key: 'params' });\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 }) === 'BlockStatement'\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 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"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../../src/linters/house/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../../src/linters/house/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAarC,qGAAqG;AACrG,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MActC,CAAC"}
|
|
@@ -3,17 +3,29 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.houseEslintPlugin = void 0;
|
|
4
4
|
const common_1 = require("./common");
|
|
5
5
|
const const_class_values_rule_1 = require("./const-class-values.rule");
|
|
6
|
+
const effect_cleanup_consistency_rule_1 = require("./effect-cleanup-consistency.rule");
|
|
6
7
|
const max_params_own_rule_1 = require("./max-params-own.rule");
|
|
8
|
+
const no_async_hook_callback_rule_1 = require("./no-async-hook-callback.rule");
|
|
9
|
+
const no_await_promise_chain_rule_1 = require("./no-await-promise-chain.rule");
|
|
10
|
+
const no_inline_await_rule_1 = require("./no-inline-await.rule");
|
|
7
11
|
const no_leaked_render_rule_1 = require("./no-leaked-render.rule");
|
|
8
12
|
const no_new_error_rule_1 = require("./no-new-error.rule");
|
|
13
|
+
const no_return_await_rule_1 = require("./no-return-await.rule");
|
|
14
|
+
const no_silent_catch_rule_1 = require("./no-silent-catch.rule");
|
|
9
15
|
/** The ESLint plugin that carries the house rules oxlint cannot express, registered as `venizia`. */
|
|
10
16
|
exports.houseEslintPlugin = {
|
|
11
17
|
meta: { name: `eslint-plugin-${common_1.HOUSE_PLUGIN_NAMESPACE}` },
|
|
12
18
|
rules: {
|
|
13
19
|
'const-class-values': const_class_values_rule_1.ConstClassValuesRule.RULE,
|
|
20
|
+
'effect-cleanup-consistency': effect_cleanup_consistency_rule_1.EffectCleanupConsistencyRule.RULE,
|
|
14
21
|
'max-params-own': max_params_own_rule_1.MaxParamsOwnRule.RULE,
|
|
22
|
+
'no-async-hook-callback': no_async_hook_callback_rule_1.NoAsyncHookCallbackRule.RULE,
|
|
23
|
+
'no-await-promise-chain': no_await_promise_chain_rule_1.NoAwaitPromiseChainRule.RULE,
|
|
24
|
+
'no-inline-await': no_inline_await_rule_1.NoInlineAwaitRule.RULE,
|
|
15
25
|
'no-leaked-render': no_leaked_render_rule_1.NoLeakedRenderRule.RULE,
|
|
16
26
|
'no-new-error': no_new_error_rule_1.NoNewErrorRule.RULE,
|
|
27
|
+
'no-return-await': no_return_await_rule_1.NoReturnAwaitRule.RULE,
|
|
28
|
+
'no-silent-catch': no_silent_catch_rule_1.NoSilentCatchRule.RULE,
|
|
17
29
|
},
|
|
18
30
|
};
|
|
19
31
|
//# sourceMappingURL=plugin.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../../src/linters/house/plugin.ts"],"names":[],"mappings":";;;AACA,qCAAkD;AAClD,uEAAiE;AACjE,+DAAyD;AACzD,mEAA6D;AAC7D,2DAAqD;
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../../src/linters/house/plugin.ts"],"names":[],"mappings":";;;AACA,qCAAkD;AAClD,uEAAiE;AACjE,uFAAiF;AACjF,+DAAyD;AACzD,+EAAwE;AACxE,+EAAwE;AACxE,iEAA2D;AAC3D,mEAA6D;AAC7D,2DAAqD;AACrD,iEAA2D;AAC3D,iEAA2D;AAE3D,qGAAqG;AACxF,QAAA,iBAAiB,GAAkB;IAC9C,IAAI,EAAE,EAAE,IAAI,EAAE,iBAAiB,+BAAsB,EAAE,EAAE;IACzD,KAAK,EAAE;QACL,oBAAoB,EAAE,8CAAoB,CAAC,IAAI;QAC/C,4BAA4B,EAAE,8DAA4B,CAAC,IAAI;QAC/D,gBAAgB,EAAE,sCAAgB,CAAC,IAAI;QACvC,wBAAwB,EAAE,qDAAuB,CAAC,IAAI;QACtD,wBAAwB,EAAE,qDAAuB,CAAC,IAAI;QACtD,iBAAiB,EAAE,wCAAiB,CAAC,IAAI;QACzC,kBAAkB,EAAE,0CAAkB,CAAC,IAAI;QAC3C,cAAc,EAAE,kCAAc,CAAC,IAAI;QACnC,iBAAiB,EAAE,wCAAiB,CAAC,IAAI;QACzC,iBAAiB,EAAE,wCAAiB,CAAC,IAAI;KAC1C;CACF,CAAC","sourcesContent":["import type { ESLint } from 'eslint';\nimport { HOUSE_PLUGIN_NAMESPACE } from './common';\nimport { ConstClassValuesRule } from './const-class-values.rule';\nimport { EffectCleanupConsistencyRule } from './effect-cleanup-consistency.rule';\nimport { MaxParamsOwnRule } from './max-params-own.rule';\nimport { NoAsyncHookCallbackRule } from './no-async-hook-callback.rule';\nimport { NoAwaitPromiseChainRule } from './no-await-promise-chain.rule';\nimport { NoInlineAwaitRule } from './no-inline-await.rule';\nimport { NoLeakedRenderRule } from './no-leaked-render.rule';\nimport { NoNewErrorRule } from './no-new-error.rule';\nimport { NoReturnAwaitRule } from './no-return-await.rule';\nimport { NoSilentCatchRule } from './no-silent-catch.rule';\n\n/** The ESLint plugin that carries the house rules oxlint cannot express, registered as `venizia`. */\nexport const houseEslintPlugin: ESLint.Plugin = {\n meta: { name: `eslint-plugin-${HOUSE_PLUGIN_NAMESPACE}` },\n rules: {\n 'const-class-values': ConstClassValuesRule.RULE,\n 'effect-cleanup-consistency': EffectCleanupConsistencyRule.RULE,\n 'max-params-own': MaxParamsOwnRule.RULE,\n 'no-async-hook-callback': NoAsyncHookCallbackRule.RULE,\n 'no-await-promise-chain': NoAwaitPromiseChainRule.RULE,\n 'no-inline-await': NoInlineAwaitRule.RULE,\n 'no-leaked-render': NoLeakedRenderRule.RULE,\n 'no-new-error': NoNewErrorRule.RULE,\n 'no-return-await': NoReturnAwaitRule.RULE,\n 'no-silent-catch': NoSilentCatchRule.RULE,\n },\n};\n"]}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/** The shared parts of the promise chain rules: what a chain call is, what a constant is, what a silent handler body is. */
|
|
2
|
+
export declare class PromiseChainSupport {
|
|
3
|
+
/** `node` without the wrappers that do not change its value (`!`, `as`, `satisfies`, `<T>`, an optional chain). */
|
|
4
|
+
static unwrap(opts: {
|
|
5
|
+
node: unknown;
|
|
6
|
+
}): unknown;
|
|
7
|
+
/** The name a member access reads: `a.name`, `a['name']`, ``a[`name`]``; `undefined` for a computed key. */
|
|
8
|
+
static memberName(opts: {
|
|
9
|
+
member: unknown;
|
|
10
|
+
}): string | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* `then`, `catch` or `finally` when `node` (after `unwrap`) is a call of that method - `p.then(f)`, `p?.catch(f)`,
|
|
13
|
+
* `p['finally'](f)` - and `undefined` for anything else. It reads the syntax only, so a thenable counts too.
|
|
14
|
+
*/
|
|
15
|
+
static chainMethodOf(opts: {
|
|
16
|
+
node: unknown;
|
|
17
|
+
}): string | undefined;
|
|
18
|
+
/**
|
|
19
|
+
* Whether a chain call (`.then`, `.catch`, `.finally`) sits anywhere on the spine of `node`: the receivers and
|
|
20
|
+
* callees a call chain is built from (`a.then(f).limit(1)` has one, `a.where(x).limit(1)` has none).
|
|
21
|
+
*/
|
|
22
|
+
static hasChainOnSpine(opts: {
|
|
23
|
+
node: unknown;
|
|
24
|
+
}): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* A value that is the same every time and reads nothing: a literal, `undefined`, a template with no `${}`, `-1`,
|
|
27
|
+
* `void 0`, and an array or object literal built only from those (`[]`, `{}`, `{ items: [] }`).
|
|
28
|
+
*/
|
|
29
|
+
static isConstant(opts: {
|
|
30
|
+
node: unknown;
|
|
31
|
+
}): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Whether the statements of a handler or a `catch` block leave no trace of the error: none at all (a comment does
|
|
34
|
+
* not count), or only `return;`, `return <constant>;` and `<name or member> = <constant>;`. Anything else - a
|
|
35
|
+
* call, a `throw`, a read of a variable - is a decision someone made, and counts as handled.
|
|
36
|
+
*/
|
|
37
|
+
static isSilentBlock(opts: {
|
|
38
|
+
statements: unknown;
|
|
39
|
+
}): boolean;
|
|
40
|
+
/** `name`, `this.name`, `a.b.c`: an assignment target that reads no computed key and calls nothing. */
|
|
41
|
+
static isPlainTarget(opts: {
|
|
42
|
+
node: unknown;
|
|
43
|
+
}): boolean;
|
|
44
|
+
/** `node` without the type-only wrappers (`as`, `satisfies`, `!`, `<T>`), keeping an optional chain. */
|
|
45
|
+
static unwrapTypes(opts: {
|
|
46
|
+
node: unknown;
|
|
47
|
+
}): unknown;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=promise-chain-support.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"promise-chain-support.d.ts","sourceRoot":"","sources":["../../../src/linters/house/promise-chain-support.ts"],"names":[],"mappings":"AAaA,4HAA4H;AAC5H,qBAAa,mBAAmB;IAC9B,mHAAmH;IACnH,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO;IAU/C,4GAA4G;IAC5G,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,OAAO,CAAA;KAAE,GAAG,MAAM,GAAG,SAAS;IAgChE;;;OAGG;IACH,MAAM,CAAC,aAAa,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,GAAG,MAAM,GAAG,SAAS;IAiBjE;;;OAGG;IACH,MAAM,CAAC,eAAe,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO;IA2BxD;;;OAGG;IACH,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO;IAiDnD;;;;OAIG;IACH,MAAM,CAAC,aAAa,CAAC,IAAI,EAAE;QAAE,UAAU,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO;IAiC5D,uGAAuG;IACvG,MAAM,CAAC,aAAa,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO;IAetD,wGAAwG;IACxG,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO;CAYrD"}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PromiseChainSupport = void 0;
|
|
4
|
+
const common_1 = require("./common");
|
|
5
|
+
const CHAIN_METHODS = new Set(['then', 'catch', 'finally']);
|
|
6
|
+
/** Wrappers that leave the value of the expression they hold unchanged: `x!`, `x as T`, `x satisfies T`, `<T>x`, `a?.b`. */
|
|
7
|
+
const VALUE_WRAPPERS = new Set([
|
|
8
|
+
'TSAsExpression',
|
|
9
|
+
'TSSatisfiesExpression',
|
|
10
|
+
'TSNonNullExpression',
|
|
11
|
+
'TSTypeAssertion',
|
|
12
|
+
'ChainExpression',
|
|
13
|
+
]);
|
|
14
|
+
const CONSTANT_UNARY_OPERATORS = new Set(['-', '+', '!', 'void']);
|
|
15
|
+
/** The shared parts of the promise chain rules: what a chain call is, what a constant is, what a silent handler body is. */
|
|
16
|
+
class PromiseChainSupport {
|
|
17
|
+
/** `node` without the wrappers that do not change its value (`!`, `as`, `satisfies`, `<T>`, an optional chain). */
|
|
18
|
+
static unwrap(opts) {
|
|
19
|
+
let current = opts.node;
|
|
20
|
+
while (VALUE_WRAPPERS.has(common_1.AstNode.getType({ node: current }) ?? '')) {
|
|
21
|
+
current = common_1.AstNode.readField({ node: current, key: 'expression' });
|
|
22
|
+
}
|
|
23
|
+
return current;
|
|
24
|
+
}
|
|
25
|
+
/** The name a member access reads: `a.name`, `a['name']`, ``a[`name`]``; `undefined` for a computed key. */
|
|
26
|
+
static memberName(opts) {
|
|
27
|
+
const { member } = opts;
|
|
28
|
+
const property = common_1.AstNode.readField({ node: member, key: 'property' });
|
|
29
|
+
if (common_1.AstNode.readField({ node: member, key: 'computed' }) !== true) {
|
|
30
|
+
const name = common_1.AstNode.readField({ node: property, key: 'name' });
|
|
31
|
+
return typeof name === 'string' ? name : undefined;
|
|
32
|
+
}
|
|
33
|
+
if (common_1.AstNode.getType({ node: property }) === 'Literal') {
|
|
34
|
+
const value = common_1.AstNode.readField({ node: property, key: 'value' });
|
|
35
|
+
return typeof value === 'string' ? value : undefined;
|
|
36
|
+
}
|
|
37
|
+
const expressions = common_1.AstNode.readField({ node: property, key: 'expressions' });
|
|
38
|
+
const quasis = common_1.AstNode.readField({ node: property, key: 'quasis' });
|
|
39
|
+
if (common_1.AstNode.getType({ node: property }) === 'TemplateLiteral' &&
|
|
40
|
+
Array.isArray(expressions) &&
|
|
41
|
+
expressions.length === 0 &&
|
|
42
|
+
Array.isArray(quasis)) {
|
|
43
|
+
const cooked = common_1.AstNode.readField({
|
|
44
|
+
node: common_1.AstNode.readField({ node: quasis[0], key: 'value' }),
|
|
45
|
+
key: 'cooked',
|
|
46
|
+
});
|
|
47
|
+
return typeof cooked === 'string' ? cooked : undefined;
|
|
48
|
+
}
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* `then`, `catch` or `finally` when `node` (after `unwrap`) is a call of that method - `p.then(f)`, `p?.catch(f)`,
|
|
53
|
+
* `p['finally'](f)` - and `undefined` for anything else. It reads the syntax only, so a thenable counts too.
|
|
54
|
+
*/
|
|
55
|
+
static chainMethodOf(opts) {
|
|
56
|
+
const call = PromiseChainSupport.unwrap({ node: opts.node });
|
|
57
|
+
if (common_1.AstNode.getType({ node: call }) !== 'CallExpression') {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
const callee = PromiseChainSupport.unwrap({
|
|
61
|
+
node: common_1.AstNode.readField({ node: call, key: 'callee' }),
|
|
62
|
+
});
|
|
63
|
+
if (common_1.AstNode.getType({ node: callee }) !== 'MemberExpression') {
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
const name = PromiseChainSupport.memberName({ member: callee });
|
|
67
|
+
return name !== undefined && CHAIN_METHODS.has(name) ? name : undefined;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Whether a chain call (`.then`, `.catch`, `.finally`) sits anywhere on the spine of `node`: the receivers and
|
|
71
|
+
* callees a call chain is built from (`a.then(f).limit(1)` has one, `a.where(x).limit(1)` has none).
|
|
72
|
+
*/
|
|
73
|
+
static hasChainOnSpine(opts) {
|
|
74
|
+
let current = PromiseChainSupport.unwrap({ node: opts.node });
|
|
75
|
+
for (;;) {
|
|
76
|
+
const type = common_1.AstNode.getType({ node: current });
|
|
77
|
+
if (type === 'CallExpression') {
|
|
78
|
+
if (PromiseChainSupport.chainMethodOf({ node: current }) !== undefined) {
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
current = PromiseChainSupport.unwrap({
|
|
82
|
+
node: common_1.AstNode.readField({ node: current, key: 'callee' }),
|
|
83
|
+
});
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (type === 'MemberExpression') {
|
|
87
|
+
current = PromiseChainSupport.unwrap({
|
|
88
|
+
node: common_1.AstNode.readField({ node: current, key: 'object' }),
|
|
89
|
+
});
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* A value that is the same every time and reads nothing: a literal, `undefined`, a template with no `${}`, `-1`,
|
|
97
|
+
* `void 0`, and an array or object literal built only from those (`[]`, `{}`, `{ items: [] }`).
|
|
98
|
+
*/
|
|
99
|
+
static isConstant(opts) {
|
|
100
|
+
const node = PromiseChainSupport.unwrapTypes({ node: opts.node });
|
|
101
|
+
const type = common_1.AstNode.getType({ node }) ?? '';
|
|
102
|
+
const constant = (child) => PromiseChainSupport.isConstant({ node: child });
|
|
103
|
+
switch (type) {
|
|
104
|
+
case 'Literal': {
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
case 'Identifier': {
|
|
108
|
+
return common_1.AstNode.readField({ node, key: 'name' }) === 'undefined';
|
|
109
|
+
}
|
|
110
|
+
case 'TemplateLiteral': {
|
|
111
|
+
const expressions = common_1.AstNode.readField({ node, key: 'expressions' });
|
|
112
|
+
return Array.isArray(expressions) && expressions.length === 0;
|
|
113
|
+
}
|
|
114
|
+
case 'UnaryExpression': {
|
|
115
|
+
return (CONSTANT_UNARY_OPERATORS.has(String(common_1.AstNode.readField({ node, key: 'operator' }))) &&
|
|
116
|
+
constant(common_1.AstNode.readField({ node, key: 'argument' })));
|
|
117
|
+
}
|
|
118
|
+
case 'ArrayExpression': {
|
|
119
|
+
const elements = common_1.AstNode.readField({ node, key: 'elements' });
|
|
120
|
+
return (Array.isArray(elements) &&
|
|
121
|
+
elements.every((element) => element === null || constant(element)));
|
|
122
|
+
}
|
|
123
|
+
case 'ObjectExpression': {
|
|
124
|
+
const properties = common_1.AstNode.readField({ node, key: 'properties' });
|
|
125
|
+
return (Array.isArray(properties) &&
|
|
126
|
+
properties.every((property) => common_1.AstNode.getType({ node: property }) === 'Property' &&
|
|
127
|
+
common_1.AstNode.readField({ node: property, key: 'computed' }) !== true &&
|
|
128
|
+
common_1.AstNode.readField({ node: property, key: 'method' }) !== true &&
|
|
129
|
+
common_1.AstNode.readField({ node: property, key: 'kind' }) === 'init' &&
|
|
130
|
+
constant(common_1.AstNode.readField({ node: property, key: 'value' }))));
|
|
131
|
+
}
|
|
132
|
+
default: {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Whether the statements of a handler or a `catch` block leave no trace of the error: none at all (a comment does
|
|
139
|
+
* not count), or only `return;`, `return <constant>;` and `<name or member> = <constant>;`. Anything else - a
|
|
140
|
+
* call, a `throw`, a read of a variable - is a decision someone made, and counts as handled.
|
|
141
|
+
*/
|
|
142
|
+
static isSilentBlock(opts) {
|
|
143
|
+
const { statements } = opts;
|
|
144
|
+
return (Array.isArray(statements) &&
|
|
145
|
+
statements.every((statement) => {
|
|
146
|
+
const type = common_1.AstNode.getType({ node: statement });
|
|
147
|
+
if (type === 'EmptyStatement') {
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
if (type === 'ReturnStatement') {
|
|
151
|
+
const argument = common_1.AstNode.readField({ node: statement, key: 'argument' });
|
|
152
|
+
return argument === null || PromiseChainSupport.isConstant({ node: argument });
|
|
153
|
+
}
|
|
154
|
+
const expression = common_1.AstNode.readField({ node: statement, key: 'expression' });
|
|
155
|
+
return (type === 'ExpressionStatement' &&
|
|
156
|
+
common_1.AstNode.getType({ node: expression }) === 'AssignmentExpression' &&
|
|
157
|
+
common_1.AstNode.readField({ node: expression, key: 'operator' }) === '=' &&
|
|
158
|
+
PromiseChainSupport.isPlainTarget({
|
|
159
|
+
node: common_1.AstNode.readField({ node: expression, key: 'left' }),
|
|
160
|
+
}) &&
|
|
161
|
+
PromiseChainSupport.isConstant({
|
|
162
|
+
node: common_1.AstNode.readField({ node: expression, key: 'right' }),
|
|
163
|
+
}));
|
|
164
|
+
}));
|
|
165
|
+
}
|
|
166
|
+
/** `name`, `this.name`, `a.b.c`: an assignment target that reads no computed key and calls nothing. */
|
|
167
|
+
static isPlainTarget(opts) {
|
|
168
|
+
const { node } = opts;
|
|
169
|
+
const type = common_1.AstNode.getType({ node });
|
|
170
|
+
if (type === 'Identifier' || type === 'ThisExpression') {
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
173
|
+
return (type === 'MemberExpression' &&
|
|
174
|
+
common_1.AstNode.readField({ node, key: 'computed' }) !== true &&
|
|
175
|
+
PromiseChainSupport.isPlainTarget({ node: common_1.AstNode.readField({ node, key: 'object' }) }));
|
|
176
|
+
}
|
|
177
|
+
/** `node` without the type-only wrappers (`as`, `satisfies`, `!`, `<T>`), keeping an optional chain. */
|
|
178
|
+
static unwrapTypes(opts) {
|
|
179
|
+
let current = opts.node;
|
|
180
|
+
while (VALUE_WRAPPERS.has(common_1.AstNode.getType({ node: current }) ?? '') &&
|
|
181
|
+
common_1.AstNode.getType({ node: current }) !== 'ChainExpression') {
|
|
182
|
+
current = common_1.AstNode.readField({ node: current, key: 'expression' });
|
|
183
|
+
}
|
|
184
|
+
return current;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
exports.PromiseChainSupport = PromiseChainSupport;
|
|
188
|
+
//# sourceMappingURL=promise-chain-support.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"promise-chain-support.js","sourceRoot":"","sources":["../../../src/linters/house/promise-chain-support.ts"],"names":[],"mappings":";;;AAAA,qCAAmC;AAEnC,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;AAC5D,4HAA4H;AAC5H,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC;IAC7B,gBAAgB;IAChB,uBAAuB;IACvB,qBAAqB;IACrB,iBAAiB;IACjB,iBAAiB;CAClB,CAAC,CAAC;AACH,MAAM,wBAAwB,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC;AAElE,4HAA4H;AAC5H,MAAa,mBAAmB;IAC9B,mHAAmH;IACnH,MAAM,CAAC,MAAM,CAAC,IAAuB;QACnC,IAAI,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC;QAExB,OAAO,cAAc,CAAC,GAAG,CAAC,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;YACpE,OAAO,GAAG,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,YAAY,EAAE,CAAC,CAAC;QACpE,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,4GAA4G;IAC5G,MAAM,CAAC,UAAU,CAAC,IAAyB;QACzC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QACxB,MAAM,QAAQ,GAAG,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,CAAC;QAEtE,IAAI,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC;YAClE,MAAM,IAAI,GAAG,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC;YAChE,OAAO,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;QACrD,CAAC;QAED,IAAI,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,KAAK,SAAS,EAAE,CAAC;YACtD,MAAM,KAAK,GAAG,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;YAClE,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;QACvD,CAAC;QAED,MAAM,WAAW,GAAG,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,aAAa,EAAE,CAAC,CAAC;QAC9E,MAAM,MAAM,GAAG,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;QACpE,IACE,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,KAAK,iBAAiB;YACzD,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC;YAC1B,WAAW,CAAC,MAAM,KAAK,CAAC;YACxB,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EACrB,CAAC;YACD,MAAM,MAAM,GAAG,gBAAO,CAAC,SAAS,CAAC;gBAC/B,IAAI,EAAE,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;gBAC1D,GAAG,EAAE,QAAQ;aACd,CAAC,CAAC;YACH,OAAO,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;QACzD,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,aAAa,CAAC,IAAuB;QAC1C,MAAM,IAAI,GAAG,mBAAmB,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAC7D,IAAI,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,KAAK,gBAAgB,EAAE,CAAC;YACzD,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,MAAM,GAAG,mBAAmB,CAAC,MAAM,CAAC;YACxC,IAAI,EAAE,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC;SACvD,CAAC,CAAC;QACH,IAAI,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,KAAK,kBAAkB,EAAE,CAAC;YAC7D,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,IAAI,GAAG,mBAAmB,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QAChE,OAAO,IAAI,KAAK,SAAS,IAAI,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1E,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,eAAe,CAAC,IAAuB;QAC5C,IAAI,OAAO,GAAG,mBAAmB,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAE9D,SAAS,CAAC;YACR,MAAM,IAAI,GAAG,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;YAEhD,IAAI,IAAI,KAAK,gBAAgB,EAAE,CAAC;gBAC9B,IAAI,mBAAmB,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,KAAK,SAAS,EAAE,CAAC;oBACvE,OAAO,IAAI,CAAC;gBACd,CAAC;gBACD,OAAO,GAAG,mBAAmB,CAAC,MAAM,CAAC;oBACnC,IAAI,EAAE,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC;iBAC1D,CAAC,CAAC;gBACH,SAAS;YACX,CAAC;YAED,IAAI,IAAI,KAAK,kBAAkB,EAAE,CAAC;gBAChC,OAAO,GAAG,mBAAmB,CAAC,MAAM,CAAC;oBACnC,IAAI,EAAE,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC;iBAC1D,CAAC,CAAC;gBACH,SAAS;YACX,CAAC;YAED,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,UAAU,CAAC,IAAuB;QACvC,MAAM,IAAI,GAAG,mBAAmB,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAClE,MAAM,IAAI,GAAG,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;QAC7C,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAE,EAAE,CAAC,mBAAmB,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAErF,QAAQ,IAAI,EAAE,CAAC;YACb,KAAK,SAAS,CAAC,CAAC,CAAC;gBACf,OAAO,IAAI,CAAC;YACd,CAAC;YACD,KAAK,YAAY,CAAC,CAAC,CAAC;gBAClB,OAAO,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,KAAK,WAAW,CAAC;YAClE,CAAC;YACD,KAAK,iBAAiB,CAAC,CAAC,CAAC;gBACvB,MAAM,WAAW,GAAG,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,aAAa,EAAE,CAAC,CAAC;gBACpE,OAAO,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,CAAC;YAChE,CAAC;YACD,KAAK,iBAAiB,CAAC,CAAC,CAAC;gBACvB,OAAO,CACL,wBAAwB,CAAC,GAAG,CAAC,MAAM,CAAC,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC;oBAClF,QAAQ,CAAC,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,CAAC,CACvD,CAAC;YACJ,CAAC;YACD,KAAK,iBAAiB,CAAC,CAAC,CAAC;gBACvB,MAAM,QAAQ,GAAG,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,CAAC;gBAC9D,OAAO,CACL,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;oBACvB,QAAQ,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,KAAK,IAAI,IAAI,QAAQ,CAAC,OAAO,CAAC,CAAC,CACnE,CAAC;YACJ,CAAC;YACD,KAAK,kBAAkB,CAAC,CAAC,CAAC;gBACxB,MAAM,UAAU,GAAG,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,YAAY,EAAE,CAAC,CAAC;gBAClE,OAAO,CACL,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC;oBACzB,UAAU,CAAC,KAAK,CACd,CAAC,QAAQ,EAAE,EAAE,CACX,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,KAAK,UAAU;wBAClD,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,KAAK,IAAI;wBAC/D,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,KAAK,IAAI;wBAC7D,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,KAAK,MAAM;wBAC7D,QAAQ,CAAC,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC,CAChE,CACF,CAAC;YACJ,CAAC;YACD,OAAO,CAAC,CAAC,CAAC;gBACR,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,aAAa,CAAC,IAA6B;QAChD,MAAM,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC;QAE5B,OAAO,CACL,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC;YACzB,UAAU,CAAC,KAAK,CAAC,CAAC,SAAS,EAAE,EAAE;gBAC7B,MAAM,IAAI,GAAG,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;gBAElD,IAAI,IAAI,KAAK,gBAAgB,EAAE,CAAC;oBAC9B,OAAO,IAAI,CAAC;gBACd,CAAC;gBAED,IAAI,IAAI,KAAK,iBAAiB,EAAE,CAAC;oBAC/B,MAAM,QAAQ,GAAG,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,CAAC;oBACzE,OAAO,QAAQ,KAAK,IAAI,IAAI,mBAAmB,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;gBACjF,CAAC;gBAED,MAAM,UAAU,GAAG,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,YAAY,EAAE,CAAC,CAAC;gBAC7E,OAAO,CACL,IAAI,KAAK,qBAAqB;oBAC9B,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,KAAK,sBAAsB;oBAChE,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,KAAK,GAAG;oBAChE,mBAAmB,CAAC,aAAa,CAAC;wBAChC,IAAI,EAAE,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;qBAC3D,CAAC;oBACF,mBAAmB,CAAC,UAAU,CAAC;wBAC7B,IAAI,EAAE,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;qBAC5D,CAAC,CACH,CAAC;YACJ,CAAC,CAAC,CACH,CAAC;IACJ,CAAC;IAED,uGAAuG;IACvG,MAAM,CAAC,aAAa,CAAC,IAAuB;QAC1C,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;QACtB,MAAM,IAAI,GAAG,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QAEvC,IAAI,IAAI,KAAK,YAAY,IAAI,IAAI,KAAK,gBAAgB,EAAE,CAAC;YACvD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,CACL,IAAI,KAAK,kBAAkB;YAC3B,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,KAAK,IAAI;YACrD,mBAAmB,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CACxF,CAAC;IACJ,CAAC;IAED,wGAAwG;IACxG,MAAM,CAAC,WAAW,CAAC,IAAuB;QACxC,IAAI,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC;QAExB,OACE,cAAc,CAAC,GAAG,CAAC,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC;YAC5D,gBAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,KAAK,iBAAiB,EACxD,CAAC;YACD,OAAO,GAAG,gBAAO,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,YAAY,EAAE,CAAC,CAAC;QACpE,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;CACF;AAzND,kDAyNC","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 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 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 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 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 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 if (AstNode.getType({ node: callee }) !== 'MemberExpression') {\n return undefined;\n }\n\n const name = PromiseChainSupport.memberName({ member: callee });\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 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 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 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 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 return argument === null || PromiseChainSupport.isConstant({ node: argument });\n }\n\n const expression = AstNode.readField({ node: statement, key: 'expression' });\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"]}
|
|
@@ -12,7 +12,7 @@ class NoRestrictedPropertiesRule {
|
|
|
12
12
|
static { this.SECURE_CONTEXT = [
|
|
13
13
|
{
|
|
14
14
|
property: 'randomUUID',
|
|
15
|
-
message: 'crypto.randomUUID exists only in a secure context (https, localhost) - on a plain-http origin it is undefined. Use
|
|
15
|
+
message: 'crypto.randomUUID exists only in a secure context (https, localhost) - on a plain-http origin it is undefined. Use UuidV4Generator.generate() from @venizia/ignis-helpers/uuid.',
|
|
16
16
|
},
|
|
17
17
|
]; }
|
|
18
18
|
static build(opts = {}) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-restricted-properties.rule.js","sourceRoot":"","sources":["../../../src/linters/rules/no-restricted-properties.rule.ts"],"names":[],"mappings":";;;AASA;;;;;GAKG;AACH,MAAa,0BAA0B;aACrB,SAAI,GAAG,0BAA0B,CAAC;aAElC,mBAAc,GAAmC;QAC/D;YACE,QAAQ,EAAE,YAAY;YACtB,OAAO,EACL,
|
|
1
|
+
{"version":3,"file":"no-restricted-properties.rule.js","sourceRoot":"","sources":["../../../src/linters/rules/no-restricted-properties.rule.ts"],"names":[],"mappings":";;;AASA;;;;;GAKG;AACH,MAAa,0BAA0B;aACrB,SAAI,GAAG,0BAA0B,CAAC;aAElC,mBAAc,GAAmC;QAC/D;YACE,QAAQ,EAAE,YAAY;YACtB,OAAO,EACL,iLAAiL;SACpL;KACF,CAAC;IAEF,MAAM,CAAC,KAAK,CACV,OAA8E,EAAE;QAEhF,MAAM,EAAE,QAAQ,GAAG,OAAO,EAAE,eAAe,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC;QAC1D,OAAO,CAAC,QAAQ,EAAE,GAAG,0BAA0B,CAAC,cAAc,EAAE,GAAG,eAAe,CAAC,CAAC;IACtF,CAAC;;AAhBH,gEAiBC","sourcesContent":["import type { TOxlintRuleEntry, TRuleSeverity } from './common';\n\n/** One forbidden property access, with the message the author sees. */\nexport interface IRestrictedProperty {\n property: string;\n object?: string;\n message: string;\n}\n\n/**\n * `no-restricted-properties`. The default bans what exists only in a secure context (https,\n * localhost): on a plain-http LAN origin or in a WebView, `crypto.randomUUID` is `undefined` and the\n * first call throws. Catches the call, `globalThis.crypto.randomUUID`, the bracket form and\n * destructuring; leaves `getRandomValues` alone.\n */\nexport class NoRestrictedPropertiesRule {\n static readonly NAME = 'no-restricted-properties';\n\n static readonly SECURE_CONTEXT: readonly IRestrictedProperty[] = [\n {\n property: 'randomUUID',\n message:\n 'crypto.randomUUID exists only in a secure context (https, localhost) - on a plain-http origin it is undefined. Use UuidV4Generator.generate() from @venizia/ignis-helpers/uuid.',\n },\n ];\n\n static build(\n opts: { severity?: TRuleSeverity; extraProperties?: IRestrictedProperty[] } = {},\n ): TOxlintRuleEntry<'no-restricted-properties'> {\n const { severity = 'error', extraProperties = [] } = opts;\n return [severity, ...NoRestrictedPropertiesRule.SECURE_CONTEXT, ...extraProperties];\n }\n}\n"]}
|
|
@@ -1,21 +1,26 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
1
|
+
export declare class RejectionHelper {
|
|
2
|
+
/**
|
|
3
|
+
* Awaits a task that must reject and returns what it rejected with; throws when the task resolves.
|
|
4
|
+
*
|
|
5
|
+
* bun types the async matchers (`expect(task).rejects` / `.resolves`) as `void`, so
|
|
6
|
+
* `await expect(task).rejects.toThrow()` is refused by `await-thenable` - and left un-awaited the
|
|
7
|
+
* assertion never runs. Awaiting the task itself needs no matcher and no cast:
|
|
8
|
+
* `RejectionHelper.expectRejection({ task, message })` or
|
|
9
|
+
* `expect(await RejectionHelper.rejectionOf({ task })).toBeInstanceOf(Error)`,
|
|
10
|
+
* and for a resolution `expect(await task).toMatchObject(...)`.
|
|
11
|
+
*/
|
|
12
|
+
static rejectionOf(opts: {
|
|
13
|
+
task: Promise<unknown>;
|
|
14
|
+
}): Promise<unknown>;
|
|
15
|
+
/**
|
|
16
|
+
* The task rejects with an Error whose message contains `message` (a string) or matches it (a
|
|
17
|
+
* RegExp). The message is compared as a string on purpose: bun 1.4.2 `toMatchObject` with an
|
|
18
|
+
* asymmetric matcher overwrites the matched property on the object it checks, so a later read of
|
|
19
|
+
* `error.message` gets the matcher back.
|
|
20
|
+
*/
|
|
21
|
+
static expectRejection(opts: {
|
|
22
|
+
task: Promise<unknown>;
|
|
23
|
+
message: string | RegExp;
|
|
24
|
+
}): Promise<void>;
|
|
25
|
+
}
|
|
21
26
|
//# sourceMappingURL=rejection.helper.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rejection.helper.d.ts","sourceRoot":"","sources":["../../src/testing/rejection.helper.ts"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"rejection.helper.d.ts","sourceRoot":"","sources":["../../src/testing/rejection.helper.ts"],"names":[],"mappings":"AAEA,qBAAa,eAAe;IAC1B;;;;;;;;;OASG;WACU,WAAW,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAU5E;;;;;OAKG;WACU,eAAe,CAAC,IAAI,EAAE;QACjC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QACvB,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;KAC1B,GAAG,OAAO,CAAC,IAAI,CAAC;CAOlB"}
|