@opensip-cli/checks-typescript 0.1.9 → 0.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -2
- package/dist/__tests__/all-checks-execute.test.d.ts.map +1 -1
- package/dist/__tests__/all-checks-execute.test.js +0 -1
- package/dist/__tests__/all-checks-execute.test.js.map +1 -1
- package/dist/__tests__/behavior-fixtures-2.test.d.ts.map +1 -1
- package/dist/__tests__/behavior-fixtures-2.test.js +0 -1
- package/dist/__tests__/behavior-fixtures-2.test.js.map +1 -1
- package/dist/__tests__/behavior-fixtures-3.test.d.ts.map +1 -1
- package/dist/__tests__/behavior-fixtures-3.test.js +0 -1
- package/dist/__tests__/behavior-fixtures-3.test.js.map +1 -1
- package/dist/__tests__/behavior-fixtures-4.test.d.ts.map +1 -1
- package/dist/__tests__/behavior-fixtures-4.test.js +0 -1
- package/dist/__tests__/behavior-fixtures-4.test.js.map +1 -1
- package/dist/__tests__/behavior-fixtures-5.test.d.ts.map +1 -1
- package/dist/__tests__/behavior-fixtures-5.test.js +0 -1
- package/dist/__tests__/behavior-fixtures-5.test.js.map +1 -1
- package/dist/__tests__/behavior-fixtures-6.test.js +10 -0
- package/dist/__tests__/behavior-fixtures-6.test.js.map +1 -1
- package/dist/__tests__/behavior-fixtures.test.d.ts.map +1 -1
- package/dist/__tests__/behavior-fixtures.test.js +2 -4
- package/dist/__tests__/behavior-fixtures.test.js.map +1 -1
- package/dist/__tests__/branch-fixtures-2.test.d.ts.map +1 -1
- package/dist/__tests__/branch-fixtures-2.test.js +0 -1
- package/dist/__tests__/branch-fixtures-2.test.js.map +1 -1
- package/dist/__tests__/branch-fixtures-3.test.d.ts.map +1 -1
- package/dist/__tests__/branch-fixtures-3.test.js +0 -1
- package/dist/__tests__/branch-fixtures-3.test.js.map +1 -1
- package/dist/__tests__/branch-fixtures.test.d.ts.map +1 -1
- package/dist/__tests__/branch-fixtures.test.js +0 -1
- package/dist/__tests__/branch-fixtures.test.js.map +1 -1
- package/dist/checks/architecture/__tests__/live-view-through-cli-live.test.d.ts +2 -0
- package/dist/checks/architecture/__tests__/live-view-through-cli-live.test.d.ts.map +1 -0
- package/dist/checks/architecture/__tests__/live-view-through-cli-live.test.js +13 -0
- package/dist/checks/architecture/__tests__/live-view-through-cli-live.test.js.map +1 -0
- package/dist/checks/architecture/contracts-schema-consistency.d.ts.map +1 -1
- package/dist/checks/architecture/contracts-schema-consistency.js +0 -3
- package/dist/checks/architecture/contracts-schema-consistency.js.map +1 -1
- package/dist/checks/architecture/drizzle-orm-migration-guardrails.d.ts.map +1 -1
- package/dist/checks/architecture/drizzle-orm-migration-guardrails.js +1 -0
- package/dist/checks/architecture/drizzle-orm-migration-guardrails.js.map +1 -1
- package/dist/checks/architecture/index.d.ts +1 -0
- package/dist/checks/architecture/index.d.ts.map +1 -1
- package/dist/checks/architecture/index.js +1 -0
- package/dist/checks/architecture/index.js.map +1 -1
- package/dist/checks/architecture/live-view-through-cli-live.d.ts +8 -0
- package/dist/checks/architecture/live-view-through-cli-live.d.ts.map +1 -0
- package/dist/checks/architecture/live-view-through-cli-live.js +43 -0
- package/dist/checks/architecture/live-view-through-cli-live.js.map +1 -0
- package/dist/checks/architecture/missing-type-exports.d.ts.map +1 -1
- package/dist/checks/architecture/missing-type-exports.js +1 -1
- package/dist/checks/architecture/missing-type-exports.js.map +1 -1
- package/dist/checks/architecture/module-coupling-fan-out.d.ts.map +1 -1
- package/dist/checks/architecture/module-coupling-fan-out.js +6 -2
- package/dist/checks/architecture/module-coupling-fan-out.js.map +1 -1
- package/dist/checks/architecture/no-bootstrap-tool-import.d.ts.map +1 -1
- package/dist/checks/architecture/no-bootstrap-tool-import.js +1 -0
- package/dist/checks/architecture/no-bootstrap-tool-import.js.map +1 -1
- package/dist/checks/architecture/no-run-done-result.d.ts.map +1 -1
- package/dist/checks/architecture/no-run-done-result.js +1 -0
- package/dist/checks/architecture/no-run-done-result.js.map +1 -1
- package/dist/checks/architecture/package-json-exports-field.d.ts.map +1 -1
- package/dist/checks/architecture/package-json-exports-field.js +1 -1
- package/dist/checks/architecture/package-json-exports-field.js.map +1 -1
- package/dist/checks/architecture/phantom-dependency-detection.d.ts.map +1 -1
- package/dist/checks/architecture/phantom-dependency-detection.js +0 -3
- package/dist/checks/architecture/phantom-dependency-detection.js.map +1 -1
- package/dist/checks/architecture/tsconfig-extends-validation.d.ts.map +1 -1
- package/dist/checks/architecture/tsconfig-extends-validation.js +0 -2
- package/dist/checks/architecture/tsconfig-extends-validation.js.map +1 -1
- package/dist/checks/quality/code-structure/__tests__/duplicate-utility-lang-substrate.test.d.ts +5 -0
- package/dist/checks/quality/code-structure/__tests__/duplicate-utility-lang-substrate.test.d.ts.map +1 -0
- package/dist/checks/quality/code-structure/__tests__/duplicate-utility-lang-substrate.test.js +17 -0
- package/dist/checks/quality/code-structure/__tests__/duplicate-utility-lang-substrate.test.js.map +1 -0
- package/dist/checks/quality/code-structure/duplicate-utility-functions-config.d.ts +18 -0
- package/dist/checks/quality/code-structure/duplicate-utility-functions-config.d.ts.map +1 -0
- package/dist/checks/quality/code-structure/duplicate-utility-functions-config.js +36 -0
- package/dist/checks/quality/code-structure/duplicate-utility-functions-config.js.map +1 -0
- package/dist/checks/quality/code-structure/duplicate-utility-functions-helpers.d.ts +15 -0
- package/dist/checks/quality/code-structure/duplicate-utility-functions-helpers.d.ts.map +1 -0
- package/dist/checks/quality/code-structure/duplicate-utility-functions-helpers.js +288 -0
- package/dist/checks/quality/code-structure/duplicate-utility-functions-helpers.js.map +1 -0
- package/dist/checks/quality/code-structure/duplicate-utility-functions.d.ts +1 -26
- package/dist/checks/quality/code-structure/duplicate-utility-functions.d.ts.map +1 -1
- package/dist/checks/quality/code-structure/duplicate-utility-functions.js +3 -407
- package/dist/checks/quality/code-structure/duplicate-utility-functions.js.map +1 -1
- package/dist/checks/quality/data-integrity/__tests__/null-safety-fp.test.js +39 -2
- package/dist/checks/quality/data-integrity/__tests__/null-safety-fp.test.js.map +1 -1
- package/dist/checks/quality/data-integrity/array-validation-detectors.d.ts +17 -0
- package/dist/checks/quality/data-integrity/array-validation-detectors.d.ts.map +1 -0
- package/dist/checks/quality/data-integrity/array-validation-detectors.js +184 -0
- package/dist/checks/quality/data-integrity/array-validation-detectors.js.map +1 -0
- package/dist/checks/quality/data-integrity/array-validation.d.ts +0 -2
- package/dist/checks/quality/data-integrity/array-validation.d.ts.map +1 -1
- package/dist/checks/quality/data-integrity/array-validation.js +2 -360
- package/dist/checks/quality/data-integrity/array-validation.js.map +1 -1
- package/dist/checks/quality/data-integrity/database-schema-validation.d.ts.map +1 -1
- package/dist/checks/quality/data-integrity/database-schema-validation.js +0 -1
- package/dist/checks/quality/data-integrity/database-schema-validation.js.map +1 -1
- package/dist/checks/quality/data-integrity/null-safety-analyze.d.ts +33 -0
- package/dist/checks/quality/data-integrity/null-safety-analyze.d.ts.map +1 -0
- package/dist/checks/quality/data-integrity/null-safety-analyze.js +164 -0
- package/dist/checks/quality/data-integrity/null-safety-analyze.js.map +1 -0
- package/dist/checks/quality/data-integrity/null-safety-config.d.ts +50 -0
- package/dist/checks/quality/data-integrity/null-safety-config.d.ts.map +1 -0
- package/dist/checks/quality/data-integrity/null-safety-config.js +69 -0
- package/dist/checks/quality/data-integrity/null-safety-config.js.map +1 -0
- package/dist/checks/quality/data-integrity/null-safety-heuristics.d.ts +76 -0
- package/dist/checks/quality/data-integrity/null-safety-heuristics.d.ts.map +1 -0
- package/dist/checks/quality/data-integrity/null-safety-heuristics.js +276 -0
- package/dist/checks/quality/data-integrity/null-safety-heuristics.js.map +1 -0
- package/dist/checks/quality/data-integrity/null-safety-prefixes.d.ts +13 -0
- package/dist/checks/quality/data-integrity/null-safety-prefixes.d.ts.map +1 -0
- package/dist/checks/quality/data-integrity/null-safety-prefixes.js +333 -0
- package/dist/checks/quality/data-integrity/null-safety-prefixes.js.map +1 -0
- package/dist/checks/quality/data-integrity/null-safety.d.ts +2 -82
- package/dist/checks/quality/data-integrity/null-safety.d.ts.map +1 -1
- package/dist/checks/quality/data-integrity/null-safety.js +3 -796
- package/dist/checks/quality/data-integrity/null-safety.js.map +1 -1
- package/dist/checks/quality/frontend/test-only-frontend-modules.d.ts.map +1 -1
- package/dist/checks/quality/frontend/test-only-frontend-modules.js +0 -2
- package/dist/checks/quality/frontend/test-only-frontend-modules.js.map +1 -1
- package/dist/checks/quality/linting/typescript-frontend.d.ts.map +1 -1
- package/dist/checks/quality/linting/typescript-frontend.js +1 -0
- package/dist/checks/quality/linting/typescript-frontend.js.map +1 -1
- package/dist/checks/quality/observability/logger-event-name-format.d.ts.map +1 -1
- package/dist/checks/quality/observability/logger-event-name-format.js +0 -1
- package/dist/checks/quality/observability/logger-event-name-format.js.map +1 -1
- package/dist/checks/quality/observability/no-hardcoded-correlation-id.d.ts.map +1 -1
- package/dist/checks/quality/observability/no-hardcoded-correlation-id.js +2 -3
- package/dist/checks/quality/observability/no-hardcoded-correlation-id.js.map +1 -1
- package/dist/checks/quality/patterns/__tests__/async-waterfall-sequential.test.d.ts +8 -0
- package/dist/checks/quality/patterns/__tests__/async-waterfall-sequential.test.d.ts.map +1 -0
- package/dist/checks/quality/patterns/__tests__/async-waterfall-sequential.test.js +87 -0
- package/dist/checks/quality/patterns/__tests__/async-waterfall-sequential.test.js.map +1 -0
- package/dist/checks/quality/patterns/__tests__/error-handling-probes.test.d.ts +2 -0
- package/dist/checks/quality/patterns/__tests__/error-handling-probes.test.d.ts.map +1 -0
- package/dist/checks/quality/patterns/__tests__/error-handling-probes.test.js +51 -0
- package/dist/checks/quality/patterns/__tests__/error-handling-probes.test.js.map +1 -0
- package/dist/checks/quality/patterns/__tests__/result-pattern-registration-guards.test.d.ts +2 -0
- package/dist/checks/quality/patterns/__tests__/result-pattern-registration-guards.test.d.ts.map +1 -0
- package/dist/checks/quality/patterns/__tests__/result-pattern-registration-guards.test.js +89 -0
- package/dist/checks/quality/patterns/__tests__/result-pattern-registration-guards.test.js.map +1 -0
- package/dist/checks/quality/patterns/__tests__/throws-documentation-analyze.test.d.ts +5 -0
- package/dist/checks/quality/patterns/__tests__/throws-documentation-analyze.test.d.ts.map +1 -0
- package/dist/checks/quality/patterns/__tests__/throws-documentation-analyze.test.js +78 -0
- package/dist/checks/quality/patterns/__tests__/throws-documentation-analyze.test.js.map +1 -0
- package/dist/checks/quality/patterns/__tests__/toctou-fp.test.js +44 -0
- package/dist/checks/quality/patterns/__tests__/toctou-fp.test.js.map +1 -1
- package/dist/checks/quality/patterns/async-waterfall-analysis.d.ts +17 -0
- package/dist/checks/quality/patterns/async-waterfall-analysis.d.ts.map +1 -0
- package/dist/checks/quality/patterns/async-waterfall-analysis.js +215 -0
- package/dist/checks/quality/patterns/async-waterfall-analysis.js.map +1 -0
- package/dist/checks/quality/patterns/async-waterfall-branch-keys.d.ts +6 -0
- package/dist/checks/quality/patterns/async-waterfall-branch-keys.d.ts.map +1 -0
- package/dist/checks/quality/patterns/async-waterfall-branch-keys.js +54 -0
- package/dist/checks/quality/patterns/async-waterfall-branch-keys.js.map +1 -0
- package/dist/checks/quality/patterns/async-waterfall-detection.d.ts.map +1 -1
- package/dist/checks/quality/patterns/async-waterfall-detection.js +3 -352
- package/dist/checks/quality/patterns/async-waterfall-detection.js.map +1 -1
- package/dist/checks/quality/patterns/containing-function-name.d.ts +3 -0
- package/dist/checks/quality/patterns/containing-function-name.d.ts.map +1 -0
- package/dist/checks/quality/patterns/containing-function-name.js +21 -0
- package/dist/checks/quality/patterns/containing-function-name.js.map +1 -0
- package/dist/checks/quality/patterns/error-handling-quality.d.ts +3 -0
- package/dist/checks/quality/patterns/error-handling-quality.d.ts.map +1 -1
- package/dist/checks/quality/patterns/error-handling-quality.js +150 -30
- package/dist/checks/quality/patterns/error-handling-quality.js.map +1 -1
- package/dist/checks/quality/patterns/result-pattern-consistency.d.ts +3 -0
- package/dist/checks/quality/patterns/result-pattern-consistency.d.ts.map +1 -1
- package/dist/checks/quality/patterns/result-pattern-consistency.js +136 -69
- package/dist/checks/quality/patterns/result-pattern-consistency.js.map +1 -1
- package/dist/checks/quality/patterns/throws-documentation-analyze.d.ts +14 -0
- package/dist/checks/quality/patterns/throws-documentation-analyze.d.ts.map +1 -0
- package/dist/checks/quality/patterns/throws-documentation-analyze.js +352 -0
- package/dist/checks/quality/patterns/throws-documentation-analyze.js.map +1 -0
- package/dist/checks/quality/patterns/throws-documentation-constants.d.ts +15 -0
- package/dist/checks/quality/patterns/throws-documentation-constants.d.ts.map +1 -0
- package/dist/checks/quality/patterns/throws-documentation-constants.js +94 -0
- package/dist/checks/quality/patterns/throws-documentation-constants.js.map +1 -0
- package/dist/checks/quality/patterns/throws-documentation.d.ts +1 -11
- package/dist/checks/quality/patterns/throws-documentation.d.ts.map +1 -1
- package/dist/checks/quality/patterns/throws-documentation.js +4 -472
- package/dist/checks/quality/patterns/throws-documentation.js.map +1 -1
- package/dist/checks/quality/patterns/toctou-race-condition-classify.d.ts +23 -0
- package/dist/checks/quality/patterns/toctou-race-condition-classify.d.ts.map +1 -0
- package/dist/checks/quality/patterns/toctou-race-condition-classify.js +125 -0
- package/dist/checks/quality/patterns/toctou-race-condition-classify.js.map +1 -0
- package/dist/checks/quality/patterns/toctou-race-condition-collection.d.ts +24 -0
- package/dist/checks/quality/patterns/toctou-race-condition-collection.d.ts.map +1 -0
- package/dist/checks/quality/patterns/toctou-race-condition-collection.js +248 -0
- package/dist/checks/quality/patterns/toctou-race-condition-collection.js.map +1 -0
- package/dist/checks/quality/patterns/toctou-race-condition-constants.d.ts +32 -0
- package/dist/checks/quality/patterns/toctou-race-condition-constants.d.ts.map +1 -0
- package/dist/checks/quality/patterns/toctou-race-condition-constants.js +115 -0
- package/dist/checks/quality/patterns/toctou-race-condition-constants.js.map +1 -0
- package/dist/checks/quality/patterns/toctou-race-condition.d.ts +1 -29
- package/dist/checks/quality/patterns/toctou-race-condition.d.ts.map +1 -1
- package/dist/checks/quality/patterns/toctou-race-condition.js +11 -536
- package/dist/checks/quality/patterns/toctou-race-condition.js.map +1 -1
- package/dist/checks/quality/unused-config-options.d.ts.map +1 -1
- package/dist/checks/quality/unused-config-options.js +0 -4
- package/dist/checks/quality/unused-config-options.js.map +1 -1
- package/dist/checks/resilience/__tests__/detached-promises-sync-detection.test.d.ts +2 -0
- package/dist/checks/resilience/__tests__/detached-promises-sync-detection.test.d.ts.map +1 -0
- package/dist/checks/resilience/__tests__/detached-promises-sync-detection.test.js +98 -0
- package/dist/checks/resilience/__tests__/detached-promises-sync-detection.test.js.map +1 -0
- package/dist/checks/resilience/callback-invocation-safe.d.ts.map +1 -1
- package/dist/checks/resilience/callback-invocation-safe.js +0 -1
- package/dist/checks/resilience/callback-invocation-safe.js.map +1 -1
- package/dist/checks/resilience/context-leakage.d.ts.map +1 -1
- package/dist/checks/resilience/context-leakage.js +1 -0
- package/dist/checks/resilience/context-leakage.js.map +1 -1
- package/dist/checks/resilience/detached-promises-detection.d.ts +7 -0
- package/dist/checks/resilience/detached-promises-detection.d.ts.map +1 -0
- package/dist/checks/resilience/detached-promises-detection.js +228 -0
- package/dist/checks/resilience/detached-promises-detection.js.map +1 -0
- package/dist/checks/resilience/detached-promises-sync-constants.d.ts +36 -0
- package/dist/checks/resilience/detached-promises-sync-constants.d.ts.map +1 -0
- package/dist/checks/resilience/detached-promises-sync-constants.js +299 -0
- package/dist/checks/resilience/detached-promises-sync-constants.js.map +1 -0
- package/dist/checks/resilience/detached-promises-sync-detection.d.ts +14 -0
- package/dist/checks/resilience/detached-promises-sync-detection.d.ts.map +1 -0
- package/dist/checks/resilience/detached-promises-sync-detection.js +69 -0
- package/dist/checks/resilience/detached-promises-sync-detection.js.map +1 -0
- package/dist/checks/resilience/detached-promises.d.ts +1 -14
- package/dist/checks/resilience/detached-promises.d.ts.map +1 -1
- package/dist/checks/resilience/detached-promises.js +2 -598
- package/dist/checks/resilience/detached-promises.js.map +1 -1
- package/dist/checks/resilience/no-raw-fetch.d.ts.map +1 -1
- package/dist/checks/resilience/no-raw-fetch.js +1 -0
- package/dist/checks/resilience/no-raw-fetch.js.map +1 -1
- package/dist/checks/resilience/no-unbounded-concurrency.d.ts.map +1 -1
- package/dist/checks/resilience/no-unbounded-concurrency.js +1 -0
- package/dist/checks/resilience/no-unbounded-concurrency.js.map +1 -1
- package/dist/checks/security/sql-injection.d.ts.map +1 -1
- package/dist/checks/security/sql-injection.js +0 -1
- package/dist/checks/security/sql-injection.js.map +1 -1
- package/dist/display/architecture.d.ts.map +1 -1
- package/dist/display/architecture.js +1 -0
- package/dist/display/architecture.js.map +1 -1
- package/dist/display/types.d.ts.map +1 -1
- package/dist/display/types.js +0 -1
- package/dist/display/types.js.map +1 -1
- package/package.json +5 -5
|
@@ -1,478 +1,14 @@
|
|
|
1
1
|
// @fitness-ignore-file no-generic-error -- Generic errors appropriate in this context
|
|
2
|
-
// @fitness-ignore-file file-length-limit -- JSDoc documentation required for public API
|
|
3
2
|
// @fitness-ignore-file no-hardcoded-timeouts -- framework default for fitness check execution timeout
|
|
4
3
|
/**
|
|
5
4
|
* @fileoverview Missing @throws JSDoc Detection Check
|
|
6
5
|
*
|
|
7
6
|
* Detects functions that contain throw statements but lack @throws JSDoc documentation.
|
|
8
|
-
*
|
|
9
7
|
*/
|
|
10
|
-
import { defineCheck,
|
|
8
|
+
import { defineCheck, isTestFile } from '@opensip-cli/fitness';
|
|
11
9
|
import { getSharedSourceFile } from '@opensip-cli/lang-typescript';
|
|
12
|
-
import
|
|
13
|
-
|
|
14
|
-
// HELPER FUNCTIONS
|
|
15
|
-
// =============================================================================
|
|
16
|
-
/**
|
|
17
|
-
* Check if node is a function-like node (function, method, or arrow function)
|
|
18
|
-
* @param n - The TypeScript AST node to check
|
|
19
|
-
* @returns True if the node is a function declaration, function expression, arrow function, or method declaration
|
|
20
|
-
*/
|
|
21
|
-
function isFunctionLikeNode(n) {
|
|
22
|
-
return (ts.isFunctionDeclaration(n) ||
|
|
23
|
-
ts.isFunctionExpression(n) ||
|
|
24
|
-
ts.isArrowFunction(n) ||
|
|
25
|
-
ts.isMethodDeclaration(n));
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Find throw statements in a node (not descending into nested functions)
|
|
29
|
-
* @param node - The AST node to search for throw statements
|
|
30
|
-
* @returns Array of throw statements found in the node (excluding nested functions)
|
|
31
|
-
*/
|
|
32
|
-
function findThrowStatements(node) {
|
|
33
|
-
const throws = [];
|
|
34
|
-
const visit = (n) => {
|
|
35
|
-
// Don't descend into nested functions
|
|
36
|
-
if (isFunctionLikeNode(n) && n !== node) {
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
if (ts.isThrowStatement(n)) {
|
|
40
|
-
throws.push(n);
|
|
41
|
-
}
|
|
42
|
-
ts.forEachChild(n, visit);
|
|
43
|
-
};
|
|
44
|
-
visit(node);
|
|
45
|
-
return throws;
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Check if a node has @throws JSDoc
|
|
49
|
-
* @param node - The AST node to check for @throws documentation
|
|
50
|
-
* @param sourceFile - The source file containing the node
|
|
51
|
-
* @returns True if the node has a @throws JSDoc comment
|
|
52
|
-
*/
|
|
53
|
-
function hasThrowsJSDoc(node, sourceFile) {
|
|
54
|
-
const fullText = sourceFile.getFullText();
|
|
55
|
-
const nodeStart = node.getFullStart();
|
|
56
|
-
const comments = ts.getLeadingCommentRanges(fullText, nodeStart);
|
|
57
|
-
if (!comments)
|
|
58
|
-
return false;
|
|
59
|
-
for (const comment of comments) {
|
|
60
|
-
const commentText = fullText.slice(comment.pos, comment.end);
|
|
61
|
-
if (commentText.includes('@throws')) {
|
|
62
|
-
return true;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
return false;
|
|
66
|
-
}
|
|
67
|
-
const ANONYMOUS_FUNCTION_NAME = '<anonymous>';
|
|
68
|
-
/**
|
|
69
|
-
* Get function name from a function declaration node
|
|
70
|
-
* @param node - The function declaration node
|
|
71
|
-
* @returns The function name, or "<anonymous>" if unnamed
|
|
72
|
-
*/
|
|
73
|
-
function getNameFromFunctionDeclaration(node) {
|
|
74
|
-
return node.name?.text ?? ANONYMOUS_FUNCTION_NAME;
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Get function name from a method declaration node
|
|
78
|
-
* @param node - The method declaration node
|
|
79
|
-
* @returns The method name, or "<anonymous>" if the name is not an identifier
|
|
80
|
-
*/
|
|
81
|
-
function getNameFromMethodDeclaration(node) {
|
|
82
|
-
return ts.isIdentifier(node.name) ? node.name.text : ANONYMOUS_FUNCTION_NAME;
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Get function name from an arrow function node
|
|
86
|
-
* @param node - The arrow function node
|
|
87
|
-
* @returns The variable name if assigned to a variable, or "<anonymous>" otherwise
|
|
88
|
-
*/
|
|
89
|
-
function getNameFromArrowFunction(node) {
|
|
90
|
-
const parent = node.parent;
|
|
91
|
-
if (ts.isVariableDeclaration(parent) && ts.isIdentifier(parent.name)) {
|
|
92
|
-
return parent.name.text;
|
|
93
|
-
}
|
|
94
|
-
return ANONYMOUS_FUNCTION_NAME;
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Get the name of a function-like node
|
|
98
|
-
* @param node - The function-like node (function declaration, method, or arrow function)
|
|
99
|
-
* @returns The function name, or "<anonymous>" if unnamed
|
|
100
|
-
*/
|
|
101
|
-
// @fitness-ignore-next-line duplicate-utility-functions -- Check-specific helper for FunctionLikeNode; each fitness check defines its own variant for its node type
|
|
102
|
-
function getFunctionName(node) {
|
|
103
|
-
if (ts.isFunctionDeclaration(node)) {
|
|
104
|
-
return getNameFromFunctionDeclaration(node);
|
|
105
|
-
}
|
|
106
|
-
if (ts.isMethodDeclaration(node)) {
|
|
107
|
-
return getNameFromMethodDeclaration(node);
|
|
108
|
-
}
|
|
109
|
-
return getNameFromArrowFunction(node);
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* Check if an arrow function is an anonymous callback that should be skipped
|
|
113
|
-
* @param node - The arrow function node to check
|
|
114
|
-
* @returns True if the arrow function is used as a callback in a call expression
|
|
115
|
-
*/
|
|
116
|
-
function isAnonymousCallback(node) {
|
|
117
|
-
const parent = node.parent;
|
|
118
|
-
return ts.isCallExpression(parent) || ts.isCallExpression(parent.parent);
|
|
119
|
-
}
|
|
120
|
-
/**
|
|
121
|
-
* Typed error classes (e.g., from a project error module).
|
|
122
|
-
* These are self-documenting and don't require @throws JSDoc.
|
|
123
|
-
*/
|
|
124
|
-
const SELF_DOCUMENTING_ERRORS = new Set([
|
|
125
|
-
// Domain errors
|
|
126
|
-
'ValidationError',
|
|
127
|
-
'AuthorizationError',
|
|
128
|
-
'NotFoundError',
|
|
129
|
-
'ConflictError',
|
|
130
|
-
'DomainError',
|
|
131
|
-
// System errors
|
|
132
|
-
'SystemError',
|
|
133
|
-
'ConfigurationError',
|
|
134
|
-
'InfrastructureError',
|
|
135
|
-
'ExternalServiceError',
|
|
136
|
-
'DatabaseError',
|
|
137
|
-
'CacheError',
|
|
138
|
-
'NetworkError',
|
|
139
|
-
// Application errors
|
|
140
|
-
'ApplicationError',
|
|
141
|
-
'OperationError',
|
|
142
|
-
'StateError',
|
|
143
|
-
'IntegrationError',
|
|
144
|
-
// HTTP errors
|
|
145
|
-
'BadRequestError',
|
|
146
|
-
'UnauthorizedError',
|
|
147
|
-
'ForbiddenError',
|
|
148
|
-
'MethodNotAllowedError',
|
|
149
|
-
'NotAcceptableError',
|
|
150
|
-
'RequestTimeoutError',
|
|
151
|
-
'GoneError',
|
|
152
|
-
'PayloadTooLargeError',
|
|
153
|
-
'UnsupportedMediaTypeError',
|
|
154
|
-
'UnprocessableEntityError',
|
|
155
|
-
'TooManyRequestsError',
|
|
156
|
-
'InternalServerError',
|
|
157
|
-
'NotImplementedError',
|
|
158
|
-
'BadGatewayError',
|
|
159
|
-
'ServiceUnavailableError',
|
|
160
|
-
'GatewayTimeoutError',
|
|
161
|
-
// Common error aliases
|
|
162
|
-
'InputValidationError',
|
|
163
|
-
'BusinessRuleError',
|
|
164
|
-
'AuthenticationError',
|
|
165
|
-
'PermissionError',
|
|
166
|
-
'ResourceNotFoundError',
|
|
167
|
-
'DuplicateResourceError',
|
|
168
|
-
'DataIntegrityError',
|
|
169
|
-
]);
|
|
170
|
-
/**
|
|
171
|
-
* Suffixes that indicate a self-documenting error type.
|
|
172
|
-
* These typed error classes are descriptive enough that @throws JSDoc adds little value.
|
|
173
|
-
*
|
|
174
|
-
* The list is intentionally broad: any class name ending in a recognizable error
|
|
175
|
-
* suffix counts as self-documenting because it carries its semantic meaning in the
|
|
176
|
-
* type name itself (callers can read and handle the typed error directly without
|
|
177
|
-
* needing prose).
|
|
178
|
-
*/
|
|
179
|
-
const SELF_DOCUMENTING_SUFFIXES = [
|
|
180
|
-
'ValidationError',
|
|
181
|
-
'NotFoundError',
|
|
182
|
-
'AuthorizationError',
|
|
183
|
-
'SystemError',
|
|
184
|
-
'DomainError',
|
|
185
|
-
'ConfigurationError',
|
|
186
|
-
'SecurityError',
|
|
187
|
-
'TimeoutError',
|
|
188
|
-
'LockError',
|
|
189
|
-
'LimitError',
|
|
190
|
-
'InfrastructureError',
|
|
191
|
-
'ApplicationError',
|
|
192
|
-
'OperationError',
|
|
193
|
-
'ErrorBuilder', // Builder pattern for typed errors
|
|
194
|
-
// Generic-sounding suffixes any project may use:
|
|
195
|
-
'NetworkError',
|
|
196
|
-
'ExecutionError',
|
|
197
|
-
'LoadError',
|
|
198
|
-
'VerifyError',
|
|
199
|
-
'ApiError',
|
|
200
|
-
'ParseError',
|
|
201
|
-
'EncodingError',
|
|
202
|
-
'DecodingError',
|
|
203
|
-
'StateError',
|
|
204
|
-
'SyncError',
|
|
205
|
-
'CaptureError',
|
|
206
|
-
'IntegrationError',
|
|
207
|
-
'PermissionError',
|
|
208
|
-
'AccessError',
|
|
209
|
-
'AuthenticationError',
|
|
210
|
-
'ResourceNotFoundError',
|
|
211
|
-
'DuplicateResourceError',
|
|
212
|
-
'DataIntegrityError',
|
|
213
|
-
'BusinessRuleError',
|
|
214
|
-
'InputValidationError',
|
|
215
|
-
// NOTE: opensip-specific suffixes — `CompositionError`, `CompositeError`,
|
|
216
|
-
// `CanonicalizationError`, `TransformError`, `VersioningError`,
|
|
217
|
-
// `TransitionError` — are NOT defaults. They live in opensip's recipe
|
|
218
|
-
// under `checks.config['throws-documentation'].additionalSelfDocumentingSuffixes`.
|
|
219
|
-
];
|
|
220
|
-
/**
|
|
221
|
-
* Build the effective self-documenting suffix list by merging built-in
|
|
222
|
-
* defaults with the recipe config slice. Called per-file from the analyze entry.
|
|
223
|
-
*/
|
|
224
|
-
function buildEffectiveSuffixes() {
|
|
225
|
-
const cfg = getCheckConfig('throws-documentation');
|
|
226
|
-
return [...SELF_DOCUMENTING_SUFFIXES, ...(cfg.additionalSelfDocumentingSuffixes ?? [])];
|
|
227
|
-
}
|
|
228
|
-
function isSelfDocumentingError(errorType, suffixes) {
|
|
229
|
-
// Check exact match
|
|
230
|
-
if (SELF_DOCUMENTING_ERRORS.has(errorType)) {
|
|
231
|
-
return true;
|
|
232
|
-
}
|
|
233
|
-
// Check if it ends with known self-documenting patterns
|
|
234
|
-
return suffixes.some((suffix) => errorType.endsWith(suffix));
|
|
235
|
-
}
|
|
236
|
-
/**
|
|
237
|
-
* Extract thrown error type from a throw statement
|
|
238
|
-
* @param throwStmt - The throw statement to analyze
|
|
239
|
-
* @param sourceFile - The source file containing the throw statement
|
|
240
|
-
* @returns The error class name (e.g., "TypeError"), or "Error" if not determinable
|
|
241
|
-
*/
|
|
242
|
-
function extractThrownType(throwStmt, sourceFile) {
|
|
243
|
-
const text = throwStmt.expression.getText(sourceFile);
|
|
244
|
-
// @fitness-ignore-next-line sonarjs-backend -- Safe regex with fixed tokens for extracting error class name
|
|
245
|
-
const typeMatch = /new\s+(\w+)/.exec(text);
|
|
246
|
-
return typeMatch?.[1] ?? 'Error';
|
|
247
|
-
}
|
|
248
|
-
/**
|
|
249
|
-
* Get unique thrown error types from throw statements
|
|
250
|
-
* @param throwStatements - Array of throw statements to analyze
|
|
251
|
-
* @param sourceFile - The source file containing the throw statements
|
|
252
|
-
* @returns Array of unique error type names found in the throw statements
|
|
253
|
-
*/
|
|
254
|
-
function getUniqueThrowTypes(throwStatements, sourceFile) {
|
|
255
|
-
if (!Array.isArray(throwStatements)) {
|
|
256
|
-
return [];
|
|
257
|
-
}
|
|
258
|
-
const thrownTypes = throwStatements.map((t) => extractThrownType(t, sourceFile));
|
|
259
|
-
return [...new Set(thrownTypes)];
|
|
260
|
-
}
|
|
261
|
-
/**
|
|
262
|
-
* Create a violation for a function missing @throws documentation
|
|
263
|
-
* @param node - The function-like node that is missing @throws documentation
|
|
264
|
-
* @param funcName - The name of the function
|
|
265
|
-
* @param throwStatements - The throw statements found in the function
|
|
266
|
-
* @param ctx - The file analysis context
|
|
267
|
-
* @returns A violation object describing the missing @throws documentation
|
|
268
|
-
* @throws {Error} If throwStatements is not an array
|
|
269
|
-
*/
|
|
270
|
-
function createMissingThrowsViolation(node, funcName, throwStatements, ctx) {
|
|
271
|
-
if (!Array.isArray(throwStatements)) {
|
|
272
|
-
throw new TypeError('throwStatements must be an array');
|
|
273
|
-
}
|
|
274
|
-
const { line, character } = ctx.sourceFile.getLineAndCharacterOfPosition(node.getStart());
|
|
275
|
-
const lineNum = line + 1;
|
|
276
|
-
const uniqueTypes = getUniqueThrowTypes(throwStatements, ctx.sourceFile);
|
|
277
|
-
return {
|
|
278
|
-
line: lineNum,
|
|
279
|
-
column: character + 1,
|
|
280
|
-
message: `Function '${funcName}' throws but lacks @throws JSDoc`,
|
|
281
|
-
severity: 'warning',
|
|
282
|
-
suggestion: `Add @throws JSDoc above the function: /** @throws {${uniqueTypes.join(' | ')}} Description of when this error is thrown */`,
|
|
283
|
-
match: funcName,
|
|
284
|
-
};
|
|
285
|
-
}
|
|
286
|
-
/**
|
|
287
|
-
* Check if a function-like node should be analyzed
|
|
288
|
-
* @param node - The function-like node to check
|
|
289
|
-
* @param funcName - The name of the function
|
|
290
|
-
* @returns True if the function should be analyzed for @throws documentation
|
|
291
|
-
*/
|
|
292
|
-
function shouldAnalyzeFunction(node, funcName) {
|
|
293
|
-
// Skip anonymous arrow function callbacks
|
|
294
|
-
if (funcName === '<anonymous>' && ts.isArrowFunction(node)) {
|
|
295
|
-
return !isAnonymousCallback(node);
|
|
296
|
-
}
|
|
297
|
-
return true;
|
|
298
|
-
}
|
|
299
|
-
/**
|
|
300
|
-
* Check if all throw statements in a function use self-documenting errors
|
|
301
|
-
* @param throwStatements - Array of throw statements to check
|
|
302
|
-
* @param sourceFile - The source file containing the throw statements
|
|
303
|
-
* @returns True if all thrown errors are self-documenting
|
|
304
|
-
*/
|
|
305
|
-
function allThrowsSelfDocumenting(throwStatements, sourceFile, suffixes) {
|
|
306
|
-
if (!Array.isArray(throwStatements) || throwStatements.length === 0) {
|
|
307
|
-
return false;
|
|
308
|
-
}
|
|
309
|
-
return throwStatements.every((stmt) => {
|
|
310
|
-
const errorType = extractThrownType(stmt, sourceFile);
|
|
311
|
-
return isSelfDocumentingError(errorType, suffixes);
|
|
312
|
-
});
|
|
313
|
-
}
|
|
314
|
-
/**
|
|
315
|
-
* Common error-field name patterns on `this` that indicate a stored-error rethrow.
|
|
316
|
-
* Used to recognise patterns like `throw this.error` (Result-pattern Failure rethrow).
|
|
317
|
-
*/
|
|
318
|
-
const ERROR_FIELD_NAME_PATTERN = /^(error|err|cause|innerError|originalError)$/i;
|
|
319
|
-
/**
|
|
320
|
-
* Generic error-variable name patterns (caught-error identifiers).
|
|
321
|
-
* Used as a fallback when we cannot statically determine the enclosing catch clause
|
|
322
|
-
* (e.g. when isRethrow is called without a function context).
|
|
323
|
-
*/
|
|
324
|
-
const ERROR_VAR_NAME_PATTERN = /^(error|err|e|ex|exception)$/i;
|
|
325
|
-
/**
|
|
326
|
-
* Collect identifier names introduced by `catch (X)` clauses anywhere inside the
|
|
327
|
-
* given function-like node (excluding nested function bodies). These names are the
|
|
328
|
-
* caught-error variables that a subsequent `throw <name>` or `throw <name>.<...>`
|
|
329
|
-
* is treated as a re-throw of.
|
|
330
|
-
*
|
|
331
|
-
* @param fnNode - The enclosing function-like node
|
|
332
|
-
* @returns Set of caught-error variable names
|
|
333
|
-
*/
|
|
334
|
-
function collectCaughtErrorNames(fnNode) {
|
|
335
|
-
const names = new Set();
|
|
336
|
-
const visit = (n) => {
|
|
337
|
-
// Don't descend into nested function bodies — their catch variables are
|
|
338
|
-
// out of scope at the throw site we care about.
|
|
339
|
-
if (isFunctionLikeNode(n) && n !== fnNode) {
|
|
340
|
-
return;
|
|
341
|
-
}
|
|
342
|
-
if (ts.isCatchClause(n) && n.variableDeclaration) {
|
|
343
|
-
const decl = n.variableDeclaration;
|
|
344
|
-
if (ts.isIdentifier(decl.name)) {
|
|
345
|
-
names.add(decl.name.text);
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
ts.forEachChild(n, visit);
|
|
349
|
-
};
|
|
350
|
-
visit(fnNode);
|
|
351
|
-
return names;
|
|
352
|
-
}
|
|
353
|
-
/**
|
|
354
|
-
* Check if a throw statement is a re-throw of a caught error.
|
|
355
|
-
*
|
|
356
|
-
* Recognised re-throw shapes:
|
|
357
|
-
* - `throw err` — bare caught-error identifier
|
|
358
|
-
* - `throw err.unwrapErr()` — typed Result rethrow
|
|
359
|
-
* - `throw this.error` — Result-pattern Failure stored-error rethrow
|
|
360
|
-
* - `throw sanitizedError(err)` — single-arg helper wrapping a caught error
|
|
361
|
-
*
|
|
362
|
-
* @param throwStmt - The throw statement to check
|
|
363
|
-
* @param sourceFile - The source file containing the throw statement
|
|
364
|
-
* @param caughtNames - Names of caught-error variables in the enclosing function
|
|
365
|
-
* @returns True if this throw statement re-throws (rather than freshly creates) an error
|
|
366
|
-
*/
|
|
367
|
-
// eslint-disable-next-line sonarjs/cognitive-complexity -- rethrow heuristic: enumerates the AST shapes that count as rethrowing (caught var, wrapping cause, scoped helpers); flatter shape would obscure the matching logic
|
|
368
|
-
function isRethrow(throwStmt, sourceFile, caughtNames) {
|
|
369
|
-
const expr = throwStmt.expression;
|
|
370
|
-
const text = expr.getText(sourceFile).trim();
|
|
371
|
-
// `new X(...)` is never a re-throw.
|
|
372
|
-
if (ts.isNewExpression(expr))
|
|
373
|
-
return false;
|
|
374
|
-
// `throw err` — bare identifier
|
|
375
|
-
if (ts.isIdentifier(expr)) {
|
|
376
|
-
if (caughtNames?.has(expr.text))
|
|
377
|
-
return true;
|
|
378
|
-
// Fallback: name matches a generic caught-error pattern (used when no context).
|
|
379
|
-
return ERROR_VAR_NAME_PATTERN.test(expr.text);
|
|
380
|
-
}
|
|
381
|
-
// `throw this.error` / `throw this.cause` — stored-error field rethrow
|
|
382
|
-
if (ts.isPropertyAccessExpression(expr) &&
|
|
383
|
-
expr.expression.kind === ts.SyntaxKind.ThisKeyword &&
|
|
384
|
-
ts.isIdentifier(expr.name) &&
|
|
385
|
-
ERROR_FIELD_NAME_PATTERN.test(expr.name.text)) {
|
|
386
|
-
return true;
|
|
387
|
-
}
|
|
388
|
-
// Result-pattern rethrows: `throw X.unwrapErr()` / `throw X.unwrap()` —
|
|
389
|
-
// the throw extracts an already-typed error from a Result and propagates it.
|
|
390
|
-
// We treat this as a rethrow regardless of whether X is in scope as a caught
|
|
391
|
-
// variable, because the wrapped error is itself a typed error from elsewhere.
|
|
392
|
-
if (ts.isCallExpression(expr) && ts.isPropertyAccessExpression(expr.expression)) {
|
|
393
|
-
const methodName = ts.isIdentifier(expr.expression.name) ? expr.expression.name.text : '';
|
|
394
|
-
if (methodName === 'unwrapErr' || methodName === 'unwrap') {
|
|
395
|
-
return true;
|
|
396
|
-
}
|
|
397
|
-
// Method invocation on a caught-error variable — also a rethrow.
|
|
398
|
-
const root = expr.expression.expression;
|
|
399
|
-
if (ts.isIdentifier(root) && caughtNames?.has(root.text)) {
|
|
400
|
-
return true;
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
// `throw sanitizedError(err)` — single-arg call wrapping a caught-error variable.
|
|
404
|
-
// Heuristic: the call has exactly one argument and that argument is an identifier
|
|
405
|
-
// matching a caught-error name (preferred) or the generic err/error pattern.
|
|
406
|
-
if (ts.isCallExpression(expr) && expr.arguments.length === 1) {
|
|
407
|
-
const arg = expr.arguments[0];
|
|
408
|
-
if (arg && ts.isIdentifier(arg)) {
|
|
409
|
-
if (caughtNames?.has(arg.text))
|
|
410
|
-
return true;
|
|
411
|
-
if (!caughtNames && ERROR_VAR_NAME_PATTERN.test(arg.text))
|
|
412
|
-
return true;
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
// Legacy fallback: bare-identifier-shaped text without 'new'. Kept for backward
|
|
416
|
-
// compatibility with call sites that don't pass the AST node.
|
|
417
|
-
return !text.includes('new ') && ERROR_VAR_NAME_PATTERN.test(text);
|
|
418
|
-
}
|
|
419
|
-
/**
|
|
420
|
-
* Analyze a function-like node for missing @throws documentation
|
|
421
|
-
* @param node - The function-like node to analyze
|
|
422
|
-
* @param ctx - The file analysis context
|
|
423
|
-
* @returns A violation if the function is missing @throws documentation, or null if compliant
|
|
424
|
-
*/
|
|
425
|
-
function analyzeFunctionNode(node, ctx) {
|
|
426
|
-
const funcName = getFunctionName(node);
|
|
427
|
-
if (!shouldAnalyzeFunction(node, funcName)) {
|
|
428
|
-
return null;
|
|
429
|
-
}
|
|
430
|
-
const throwStatements = findThrowStatements(node);
|
|
431
|
-
if (throwStatements.length === 0) {
|
|
432
|
-
return null;
|
|
433
|
-
}
|
|
434
|
-
// Skip if already has @throws documentation
|
|
435
|
-
if (hasThrowsJSDoc(node, ctx.sourceFile)) {
|
|
436
|
-
return null;
|
|
437
|
-
}
|
|
438
|
-
// Skip if all throws are self-documenting typed errors
|
|
439
|
-
if (allThrowsSelfDocumenting(throwStatements, ctx.sourceFile, ctx.selfDocumentingSuffixes)) {
|
|
440
|
-
return null;
|
|
441
|
-
}
|
|
442
|
-
// Skip if all throws are re-throws (error propagation). We pass the set of
|
|
443
|
-
// caught-error variable names declared in any `catch (X)` clause inside the
|
|
444
|
-
// function so that `throw err`, `throw err.unwrapErr()`, and
|
|
445
|
-
// `throw sanitizedError(err)` are recognised as rethrows.
|
|
446
|
-
const caughtNames = collectCaughtErrorNames(node);
|
|
447
|
-
if (throwStatements.every((stmt) => isRethrow(stmt, ctx.sourceFile, caughtNames))) {
|
|
448
|
-
return null;
|
|
449
|
-
}
|
|
450
|
-
return createMissingThrowsViolation(node, funcName, throwStatements, ctx);
|
|
451
|
-
}
|
|
452
|
-
/**
|
|
453
|
-
* Analyze a file for missing @throws documentation
|
|
454
|
-
* @param ctx - The file analysis context containing source file and metadata
|
|
455
|
-
* @returns Array of violations for functions missing @throws documentation
|
|
456
|
-
*/
|
|
457
|
-
function analyzeFile(ctx) {
|
|
458
|
-
const violations = [];
|
|
459
|
-
const visit = (node) => {
|
|
460
|
-
if (ts.isFunctionDeclaration(node) ||
|
|
461
|
-
ts.isMethodDeclaration(node) ||
|
|
462
|
-
ts.isArrowFunction(node)) {
|
|
463
|
-
const violation = analyzeFunctionNode(node, ctx);
|
|
464
|
-
if (violation) {
|
|
465
|
-
violations.push(violation);
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
ts.forEachChild(node, visit);
|
|
469
|
-
};
|
|
470
|
-
visit(ctx.sourceFile);
|
|
471
|
-
return violations;
|
|
472
|
-
}
|
|
473
|
-
// =============================================================================
|
|
474
|
-
// CHECK DEFINITION
|
|
475
|
-
// =============================================================================
|
|
10
|
+
import { analyzeFile } from './throws-documentation-analyze.js';
|
|
11
|
+
import { buildEffectiveSuffixes } from './throws-documentation-constants.js';
|
|
476
12
|
/**
|
|
477
13
|
* Check: quality/throws-documentation
|
|
478
14
|
*
|
|
@@ -494,14 +30,10 @@ export const throwsDocumentation = defineCheck({
|
|
|
494
30
|
**Scope:** Codebase-specific convention enforcing error handling standards`,
|
|
495
31
|
tags: ['quality', 'documentation', 'best-practices'],
|
|
496
32
|
fileTypes: ['ts'],
|
|
497
|
-
timeout: 180_000,
|
|
33
|
+
timeout: 180_000,
|
|
498
34
|
analyze(content, filePath) {
|
|
499
|
-
// Skip test files — assertion failures, anonymous test callbacks, and
|
|
500
|
-
// fixture helpers are not public-API surface. Matches the convention in
|
|
501
|
-
// `null-safety`. Public-API throws are documented in non-test code.
|
|
502
35
|
if (isTestFile(filePath))
|
|
503
36
|
return [];
|
|
504
|
-
// Quick filter
|
|
505
37
|
if (!content.includes('throw ')) {
|
|
506
38
|
return [];
|
|
507
39
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"throws-documentation.js","sourceRoot":"","sources":["../../../../src/checks/quality/patterns/throws-documentation.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,wFAAwF;AACxF,sGAAsG;AACtG;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,UAAU,EAAuB,MAAM,sBAAsB,CAAC;AACpG,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AA6BjC,gFAAgF;AAChF,mBAAmB;AACnB,gFAAgF;AAEhF;;;;GAIG;AACH,SAAS,kBAAkB,CAAC,CAAU;IACpC,OAAO,CACL,EAAE,CAAC,qBAAqB,CAAC,CAAC,CAAC;QAC3B,EAAE,CAAC,oBAAoB,CAAC,CAAC,CAAC;QAC1B,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC;QACrB,EAAE,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAC1B,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAS,mBAAmB,CAAC,IAAa;IACxC,MAAM,MAAM,GAAwB,EAAE,CAAC;IAEvC,MAAM,KAAK,GAAG,CAAC,CAAU,EAAQ,EAAE;QACjC,sCAAsC;QACtC,IAAI,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;YACxC,OAAO;QACT,CAAC;QACD,IAAI,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3B,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACjB,CAAC;QACD,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAC5B,CAAC,CAAC;IAEF,KAAK,CAAC,IAAI,CAAC,CAAC;IACZ,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;GAKG;AACH,SAAS,cAAc,CAAC,IAAa,EAAE,UAAyB;IAC9D,MAAM,QAAQ,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;IAC1C,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;IACtC,MAAM,QAAQ,GAAG,EAAE,CAAC,uBAAuB,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAEjE,IAAI,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAC;IAE5B,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;QAC7D,IAAI,WAAW,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YACpC,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,uBAAuB,GAAG,aAAa,CAAC;AAE9C;;;;GAIG;AACH,SAAS,8BAA8B,CAAC,IAA4B;IAClE,OAAO,IAAI,CAAC,IAAI,EAAE,IAAI,IAAI,uBAAuB,CAAC;AACpD,CAAC;AAED;;;;GAIG;AACH,SAAS,4BAA4B,CAAC,IAA0B;IAC9D,OAAO,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,uBAAuB,CAAC;AAC/E,CAAC;AAED;;;;GAIG;AACH,SAAS,wBAAwB,CAAC,IAAsB;IACtD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IAC3B,IAAI,EAAE,CAAC,qBAAqB,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QACrE,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;IAC1B,CAAC;IACD,OAAO,uBAAuB,CAAC;AACjC,CAAC;AAED;;;;GAIG;AACH,oKAAoK;AACpK,SAAS,eAAe,CAAC,IAAsB;IAC7C,IAAI,EAAE,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,OAAO,8BAA8B,CAAC,IAAI,CAAC,CAAC;IAC9C,CAAC;IACD,IAAI,EAAE,CAAC,mBAAmB,CAAC,IAAI,CAAC,EAAE,CAAC;QACjC,OAAO,4BAA4B,CAAC,IAAI,CAAC,CAAC;IAC5C,CAAC;IACD,OAAO,wBAAwB,CAAC,IAAI,CAAC,CAAC;AACxC,CAAC;AAED;;;;GAIG;AACH,SAAS,mBAAmB,CAAC,IAAsB;IACjD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IAC3B,OAAO,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AAC3E,CAAC;AAED;;;GAGG;AACH,MAAM,uBAAuB,GAAG,IAAI,GAAG,CAAC;IACtC,gBAAgB;IAChB,iBAAiB;IACjB,oBAAoB;IACpB,eAAe;IACf,eAAe;IACf,aAAa;IACb,gBAAgB;IAChB,aAAa;IACb,oBAAoB;IACpB,qBAAqB;IACrB,sBAAsB;IACtB,eAAe;IACf,YAAY;IACZ,cAAc;IACd,qBAAqB;IACrB,kBAAkB;IAClB,gBAAgB;IAChB,YAAY;IACZ,kBAAkB;IAClB,cAAc;IACd,iBAAiB;IACjB,mBAAmB;IACnB,gBAAgB;IAChB,uBAAuB;IACvB,oBAAoB;IACpB,qBAAqB;IACrB,WAAW;IACX,sBAAsB;IACtB,2BAA2B;IAC3B,0BAA0B;IAC1B,sBAAsB;IACtB,qBAAqB;IACrB,qBAAqB;IACrB,iBAAiB;IACjB,yBAAyB;IACzB,qBAAqB;IACrB,uBAAuB;IACvB,sBAAsB;IACtB,mBAAmB;IACnB,qBAAqB;IACrB,iBAAiB;IACjB,uBAAuB;IACvB,wBAAwB;IACxB,oBAAoB;CACrB,CAAC,CAAC;AAEH;;;;;;;;GAQG;AACH,MAAM,yBAAyB,GAAG;IAChC,iBAAiB;IACjB,eAAe;IACf,oBAAoB;IACpB,aAAa;IACb,aAAa;IACb,oBAAoB;IACpB,eAAe;IACf,cAAc;IACd,WAAW;IACX,YAAY;IACZ,qBAAqB;IACrB,kBAAkB;IAClB,gBAAgB;IAChB,cAAc,EAAE,mCAAmC;IACnD,iDAAiD;IACjD,cAAc;IACd,gBAAgB;IAChB,WAAW;IACX,aAAa;IACb,UAAU;IACV,YAAY;IACZ,eAAe;IACf,eAAe;IACf,YAAY;IACZ,WAAW;IACX,cAAc;IACd,kBAAkB;IAClB,iBAAiB;IACjB,aAAa;IACb,qBAAqB;IACrB,uBAAuB;IACvB,wBAAwB;IACxB,oBAAoB;IACpB,mBAAmB;IACnB,sBAAsB;IACtB,0EAA0E;IAC1E,gEAAgE;IAChE,sEAAsE;IACtE,mFAAmF;CACpF,CAAC;AAEF;;;GAGG;AACH,SAAS,sBAAsB;IAC7B,MAAM,GAAG,GAAG,cAAc,CAAkB,sBAAsB,CAAC,CAAC;IACpE,OAAO,CAAC,GAAG,yBAAyB,EAAE,GAAG,CAAC,GAAG,CAAC,iCAAiC,IAAI,EAAE,CAAC,CAAC,CAAC;AAC1F,CAAC;AAED,SAAS,sBAAsB,CAAC,SAAiB,EAAE,QAA2B;IAC5E,oBAAoB;IACpB,IAAI,uBAAuB,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3C,OAAO,IAAI,CAAC;IACd,CAAC;IACD,wDAAwD;IACxD,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED;;;;;GAKG;AACH,SAAS,iBAAiB,CAAC,SAA4B,EAAE,UAAyB;IAChF,MAAM,IAAI,GAAG,SAAS,CAAC,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACtD,4GAA4G;IAC5G,MAAM,SAAS,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3C,OAAO,SAAS,EAAE,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC;AACnC,CAAC;AAED;;;;;GAKG;AACH,SAAS,mBAAmB,CAC1B,eAAoC,EACpC,UAAyB;IAEzB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC;QACpC,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,WAAW,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC;IACjF,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC;AACnC,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,4BAA4B,CACnC,IAAsB,EACtB,QAAgB,EAChB,eAAoC,EACpC,GAAwB;IAExB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,SAAS,CAAC,kCAAkC,CAAC,CAAC;IAC1D,CAAC;IACD,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,GAAG,CAAC,UAAU,CAAC,6BAA6B,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC1F,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,CAAC;IACzB,MAAM,WAAW,GAAG,mBAAmB,CAAC,eAAe,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;IAEzE,OAAO;QACL,IAAI,EAAE,OAAO;QACb,MAAM,EAAE,SAAS,GAAG,CAAC;QACrB,OAAO,EAAE,aAAa,QAAQ,kCAAkC;QAChE,QAAQ,EAAE,SAAS;QACnB,UAAU,EAAE,sDAAsD,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,+CAA+C;QACxI,KAAK,EAAE,QAAQ;KAChB,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAS,qBAAqB,CAAC,IAAsB,EAAE,QAAgB;IACrE,0CAA0C;IAC1C,IAAI,QAAQ,KAAK,aAAa,IAAI,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3D,OAAO,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,SAAS,wBAAwB,CAC/B,eAAoC,EACpC,UAAyB,EACzB,QAA2B;IAE3B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpE,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE;QACpC,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QACtD,OAAO,sBAAsB,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,wBAAwB,GAAG,+CAA+C,CAAC;AAEjF;;;;GAIG;AACH,MAAM,sBAAsB,GAAG,+BAA+B,CAAC;AAE/D;;;;;;;;GAQG;AACH,SAAS,uBAAuB,CAAC,MAAe;IAC9C,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,MAAM,KAAK,GAAG,CAAC,CAAU,EAAQ,EAAE;QACjC,wEAAwE;QACxE,gDAAgD;QAChD,IAAI,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,MAAM,EAAE,CAAC;YAC1C,OAAO;QACT,CAAC;QACD,IAAI,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,mBAAmB,EAAE,CAAC;YACjD,MAAM,IAAI,GAAG,CAAC,CAAC,mBAAmB,CAAC;YACnC,IAAI,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC/B,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;QACD,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAC5B,CAAC,CAAC;IACF,KAAK,CAAC,MAAM,CAAC,CAAC;IACd,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,8NAA8N;AAC9N,SAAS,SAAS,CAChB,SAA4B,EAC5B,UAAyB,EACzB,WAAyB;IAEzB,MAAM,IAAI,GAAG,SAAS,CAAC,UAAU,CAAC;IAClC,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,IAAI,EAAE,CAAC;IAE7C,oCAAoC;IACpC,IAAI,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAE3C,gCAAgC;IAChC,IAAI,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1B,IAAI,WAAW,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QAC7C,gFAAgF;QAChF,OAAO,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChD,CAAC;IAED,uEAAuE;IACvE,IACE,EAAE,CAAC,0BAA0B,CAAC,IAAI,CAAC;QACnC,IAAI,CAAC,UAAU,CAAC,IAAI,KAAK,EAAE,CAAC,UAAU,CAAC,WAAW;QAClD,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;QAC1B,wBAAwB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAC7C,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,wEAAwE;IACxE,6EAA6E;IAC7E,6EAA6E;IAC7E,8EAA8E;IAC9E,IAAI,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,0BAA0B,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QAChF,MAAM,UAAU,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1F,IAAI,UAAU,KAAK,WAAW,IAAI,UAAU,KAAK,QAAQ,EAAE,CAAC;YAC1D,OAAO,IAAI,CAAC;QACd,CAAC;QACD,iEAAiE;QACjE,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;QACxC,IAAI,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,WAAW,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACzD,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,kFAAkF;IAClF,kFAAkF;IAClF,6EAA6E;IAC7E,IAAI,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7D,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QAC9B,IAAI,GAAG,IAAI,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;YAChC,IAAI,WAAW,EAAE,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,OAAO,IAAI,CAAC;YAC5C,IAAI,CAAC,WAAW,IAAI,sBAAsB,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,OAAO,IAAI,CAAC;QACzE,CAAC;IACH,CAAC;IAED,gFAAgF;IAChF,8DAA8D;IAC9D,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACrE,CAAC;AAED;;;;;GAKG;AACH,SAAS,mBAAmB,CAC1B,IAAsB,EACtB,GAAwB;IAExB,MAAM,QAAQ,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IAEvC,IAAI,CAAC,qBAAqB,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,CAAC;QAC3C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,eAAe,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;IAElD,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,4CAA4C;IAC5C,IAAI,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;QACzC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,uDAAuD;IACvD,IAAI,wBAAwB,CAAC,eAAe,EAAE,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,uBAAuB,CAAC,EAAE,CAAC;QAC3F,OAAO,IAAI,CAAC;IACd,CAAC;IAED,2EAA2E;IAC3E,4EAA4E;IAC5E,6DAA6D;IAC7D,0DAA0D;IAC1D,MAAM,WAAW,GAAG,uBAAuB,CAAC,IAAI,CAAC,CAAC;IAClD,IAAI,eAAe,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC;QAClF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,4BAA4B,CAAC,IAAI,EAAE,QAAQ,EAAE,eAAe,EAAE,GAAG,CAAC,CAAC;AAC5E,CAAC;AAED;;;;GAIG;AACH,SAAS,WAAW,CAAC,GAAwB;IAC3C,MAAM,UAAU,GAAqB,EAAE,CAAC;IAExC,MAAM,KAAK,GAAG,CAAC,IAAa,EAAQ,EAAE;QACpC,IACE,EAAE,CAAC,qBAAqB,CAAC,IAAI,CAAC;YAC9B,EAAE,CAAC,mBAAmB,CAAC,IAAI,CAAC;YAC5B,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,EACxB,CAAC;YACD,MAAM,SAAS,GAAG,mBAAmB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YACjD,IAAI,SAAS,EAAE,CAAC;gBACd,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC7B,CAAC;QACH,CAAC;QACD,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC/B,CAAC,CAAC;IAEF,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACtB,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,gFAAgF;AAChF,mBAAmB;AACnB,gFAAgF;AAEhF;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,WAAW,CAAC;IAC7C,EAAE,EAAE,sCAAsC;IAC1C,IAAI,EAAE,sBAAsB;IAC5B,KAAK,EAAE,EAAE,SAAS,EAAE,CAAC,YAAY,CAAC,EAAE,QAAQ,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,KAAK,CAAC,EAAE;IAC9E,aAAa,EAAE,eAAe;IAE9B,UAAU,EAAE,MAAM;IAClB,WAAW,EAAE,8DAA8D;IAC3E,eAAe,EAAE;;;;;;2EAMwD;IACzE,IAAI,EAAE,CAAC,SAAS,EAAE,eAAe,EAAE,gBAAgB,CAAC;IACpD,SAAS,EAAE,CAAC,IAAI,CAAC;IACjB,OAAO,EAAE,OAAO,EAAE,0DAA0D;IAE5E,OAAO,CAAC,OAAO,EAAE,QAAQ;QACvB,sEAAsE;QACtE,wEAAwE;QACxE,oEAAoE;QACpE,IAAI,UAAU,CAAC,QAAQ,CAAC;YAAE,OAAO,EAAE,CAAC;QAEpC,eAAe;QACf,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YAChC,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,UAAU,GAAG,mBAAmB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC1D,IAAI,CAAC,UAAU;YAAE,OAAO,EAAE,CAAC;QAE3B,OAAO,WAAW,CAAC;YACjB,UAAU;YACV,OAAO;YACP,QAAQ;YACR,uBAAuB,EAAE,sBAAsB,EAAE;SAClD,CAAC,CAAC;IACL,CAAC;CACF,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"throws-documentation.js","sourceRoot":"","sources":["../../../../src/checks/quality/patterns/throws-documentation.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,sGAAsG;AACtG;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAEnE,OAAO,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAE7E;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,WAAW,CAAC;IAC7C,EAAE,EAAE,sCAAsC;IAC1C,IAAI,EAAE,sBAAsB;IAC5B,KAAK,EAAE,EAAE,SAAS,EAAE,CAAC,YAAY,CAAC,EAAE,QAAQ,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,KAAK,CAAC,EAAE;IAC9E,aAAa,EAAE,eAAe;IAE9B,UAAU,EAAE,MAAM;IAClB,WAAW,EAAE,8DAA8D;IAC3E,eAAe,EAAE;;;;;;2EAMwD;IACzE,IAAI,EAAE,CAAC,SAAS,EAAE,eAAe,EAAE,gBAAgB,CAAC;IACpD,SAAS,EAAE,CAAC,IAAI,CAAC;IACjB,OAAO,EAAE,OAAO;IAEhB,OAAO,CAAC,OAAO,EAAE,QAAQ;QACvB,IAAI,UAAU,CAAC,QAAQ,CAAC;YAAE,OAAO,EAAE,CAAC;QAEpC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YAChC,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,UAAU,GAAG,mBAAmB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC1D,IAAI,CAAC,UAAU;YAAE,OAAO,EAAE,CAAC;QAE3B,OAAO,WAAW,CAAC;YACjB,UAAU;YACV,OAAO;YACP,QAAQ;YACR,uBAAuB,EAAE,sBAAsB,EAAE;SAClD,CAAC,CAAC;IACL,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Call-site classification for the TOCTOU race-condition check.
|
|
3
|
+
*/
|
|
4
|
+
import { type FunctionLikeNode } from './toctou-race-condition-collection.js';
|
|
5
|
+
import { KIND_READ_LOCAL, KIND_READ_SHARED, KIND_UPDATE_LOCAL, KIND_UPDATE_SHARED } from './toctou-race-condition-constants.js';
|
|
6
|
+
/** Classification of a `<receiver>.<method>(...)` call site. */
|
|
7
|
+
export type CallKind = {
|
|
8
|
+
kind: typeof KIND_READ_SHARED;
|
|
9
|
+
} | {
|
|
10
|
+
kind: typeof KIND_UPDATE_SHARED;
|
|
11
|
+
} | {
|
|
12
|
+
kind: typeof KIND_READ_LOCAL;
|
|
13
|
+
} | {
|
|
14
|
+
kind: typeof KIND_UPDATE_LOCAL;
|
|
15
|
+
} | {
|
|
16
|
+
kind: 'atomic-sql-write';
|
|
17
|
+
} | {
|
|
18
|
+
kind: 'unrelated';
|
|
19
|
+
};
|
|
20
|
+
export declare function classifyFunctionCalls(node: FunctionLikeNode, localCollections: Set<string>, classCacheFields: Set<string>, localObjectCollectionKeys: Set<string>): {
|
|
21
|
+
hasSharedReadAndUpdateOnSameReceiver: boolean;
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=toctou-race-condition-classify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toctou-race-condition-classify.d.ts","sourceRoot":"","sources":["../../../../src/checks/quality/patterns/toctou-race-condition-classify.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAIL,KAAK,gBAAgB,EACtB,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAIL,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EACnB,MAAM,sCAAsC,CAAC;AAE9C,gEAAgE;AAChE,MAAM,MAAM,QAAQ,GAChB;IAAE,IAAI,EAAE,OAAO,gBAAgB,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,OAAO,kBAAkB,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,OAAO,eAAe,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,OAAO,iBAAiB,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,kBAAkB,CAAA;CAAE,GAC5B;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,CAAC;AAqF1B,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,gBAAgB,EACtB,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,EAC7B,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,EAC7B,yBAAyB,EAAE,GAAG,CAAC,MAAM,CAAC,GACrC;IAAE,oCAAoC,EAAE,OAAO,CAAA;CAAE,CAwCnD"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Call-site classification for the TOCTOU race-condition check.
|
|
3
|
+
*/
|
|
4
|
+
import * as ts from 'typescript';
|
|
5
|
+
import { getReceiverChainText, isFunctionLikeNode, isInMemoryCacheReceiverText, } from './toctou-race-condition-collection.js';
|
|
6
|
+
import { isDrizzleAtomicWriteMethod, isReadMethod, isUpdateMethod, KIND_READ_LOCAL, KIND_READ_SHARED, KIND_UPDATE_LOCAL, KIND_UPDATE_SHARED, } from './toctou-race-condition-constants.js';
|
|
7
|
+
function isAtomicSqlExecute(call) {
|
|
8
|
+
if (!ts.isPropertyAccessExpression(call.expression))
|
|
9
|
+
return false;
|
|
10
|
+
if (call.expression.name.text !== 'execute')
|
|
11
|
+
return false;
|
|
12
|
+
const arg = call.arguments[0];
|
|
13
|
+
if (!arg)
|
|
14
|
+
return false;
|
|
15
|
+
if (ts.isTaggedTemplateExpression(arg) && ts.isIdentifier(arg.tag) && arg.tag.text === 'sql')
|
|
16
|
+
return true;
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
function isDrizzleAtomicWrite(call) {
|
|
20
|
+
if (!ts.isPropertyAccessExpression(call.expression))
|
|
21
|
+
return false;
|
|
22
|
+
const methodName = call.expression.name.text;
|
|
23
|
+
if (!isDrizzleAtomicWriteMethod(methodName))
|
|
24
|
+
return false;
|
|
25
|
+
const receiver = call.expression.expression;
|
|
26
|
+
if (ts.isIdentifier(receiver)) {
|
|
27
|
+
const r = receiver.text;
|
|
28
|
+
if (r === 'db' || r === 'tx' || /Db$|Tx$/.test(r))
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
function getReceiverName(call) {
|
|
34
|
+
if (!ts.isPropertyAccessExpression(call.expression))
|
|
35
|
+
return null;
|
|
36
|
+
const receiver = call.expression.expression;
|
|
37
|
+
if (receiver.kind === ts.SyntaxKind.ThisKeyword) {
|
|
38
|
+
return { name: call.expression.name.text, isThisField: true };
|
|
39
|
+
}
|
|
40
|
+
const chain = getReceiverChainText(receiver);
|
|
41
|
+
if (!chain)
|
|
42
|
+
return null;
|
|
43
|
+
if (chain.startsWith('this.')) {
|
|
44
|
+
return { name: chain.slice('this.'.length), isThisField: true };
|
|
45
|
+
}
|
|
46
|
+
return { name: chain, isThisField: false };
|
|
47
|
+
}
|
|
48
|
+
function isLocalReceiver(receiver, ctx) {
|
|
49
|
+
if (receiver.isThisField) {
|
|
50
|
+
return ctx.classCacheFields.has(receiver.name) || isInMemoryCacheReceiverText(receiver.name);
|
|
51
|
+
}
|
|
52
|
+
return (ctx.localCollections.has(receiver.name) ||
|
|
53
|
+
ctx.localObjectCollectionKeys.has(receiver.name) ||
|
|
54
|
+
isInMemoryCacheReceiverText(receiver.name));
|
|
55
|
+
}
|
|
56
|
+
function classifyCall(call, ctx) {
|
|
57
|
+
if (isAtomicSqlExecute(call))
|
|
58
|
+
return { kind: 'atomic-sql-write' };
|
|
59
|
+
if (isDrizzleAtomicWrite(call))
|
|
60
|
+
return { kind: 'atomic-sql-write' };
|
|
61
|
+
if (!ts.isPropertyAccessExpression(call.expression))
|
|
62
|
+
return { kind: 'unrelated' };
|
|
63
|
+
const methodName = call.expression.name.text;
|
|
64
|
+
const isRead = isReadMethod(methodName);
|
|
65
|
+
const isUpdate = isUpdateMethod(methodName);
|
|
66
|
+
if (!isRead && !isUpdate)
|
|
67
|
+
return { kind: 'unrelated' };
|
|
68
|
+
const receiver = getReceiverName(call);
|
|
69
|
+
if (!receiver) {
|
|
70
|
+
return { kind: isRead ? KIND_READ_SHARED : KIND_UPDATE_SHARED };
|
|
71
|
+
}
|
|
72
|
+
if (isLocalReceiver(receiver, ctx)) {
|
|
73
|
+
return { kind: isRead ? KIND_READ_LOCAL : KIND_UPDATE_LOCAL };
|
|
74
|
+
}
|
|
75
|
+
return { kind: isRead ? KIND_READ_SHARED : KIND_UPDATE_SHARED };
|
|
76
|
+
}
|
|
77
|
+
/* eslint-disable sonarjs/cognitive-complexity -- TOCTOU classifier AST visitor */
|
|
78
|
+
export function classifyFunctionCalls(node, localCollections, classCacheFields, localObjectCollectionKeys) {
|
|
79
|
+
const ctx = { localCollections, classCacheFields, localObjectCollectionKeys };
|
|
80
|
+
const perReceiver = new Map();
|
|
81
|
+
let hasReadOnUnknownReceiver = false;
|
|
82
|
+
let hasUpdateOnUnknownReceiver = false;
|
|
83
|
+
const visit = (n) => {
|
|
84
|
+
if (n !== node && isFunctionLikeNode(n))
|
|
85
|
+
return;
|
|
86
|
+
if (ts.isCallExpression(n)) {
|
|
87
|
+
const cls = classifyCall(n, ctx);
|
|
88
|
+
if (cls.kind === 'read-shared' || cls.kind === 'update-shared') {
|
|
89
|
+
const recv = getReceiverName(n);
|
|
90
|
+
if (recv) {
|
|
91
|
+
const key = recv.isThisField ? `this.${recv.name}` : recv.name;
|
|
92
|
+
let entry = perReceiver.get(key);
|
|
93
|
+
if (!entry) {
|
|
94
|
+
entry = { read: false, update: false };
|
|
95
|
+
perReceiver.set(key, entry);
|
|
96
|
+
}
|
|
97
|
+
if (cls.kind === 'read-shared')
|
|
98
|
+
entry.read = true;
|
|
99
|
+
else
|
|
100
|
+
entry.update = true;
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
if (cls.kind === 'read-shared')
|
|
104
|
+
hasReadOnUnknownReceiver = true;
|
|
105
|
+
else
|
|
106
|
+
hasUpdateOnUnknownReceiver = true;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
ts.forEachChild(n, visit);
|
|
111
|
+
};
|
|
112
|
+
if (node.body)
|
|
113
|
+
visit(node.body);
|
|
114
|
+
for (const entry of perReceiver.values()) {
|
|
115
|
+
if (entry.read && entry.update) {
|
|
116
|
+
return { hasSharedReadAndUpdateOnSameReceiver: true };
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (hasReadOnUnknownReceiver && hasUpdateOnUnknownReceiver) {
|
|
120
|
+
return { hasSharedReadAndUpdateOnSameReceiver: true };
|
|
121
|
+
}
|
|
122
|
+
return { hasSharedReadAndUpdateOnSameReceiver: false };
|
|
123
|
+
}
|
|
124
|
+
/* eslint-enable sonarjs/cognitive-complexity */
|
|
125
|
+
//# sourceMappingURL=toctou-race-condition-classify.js.map
|