@nielspeter/eess-ts 0.5.1 → 0.6.0
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 +1 -1
- package/dist/builders/class-rule-builder.d.ts +6 -3
- package/dist/builders/class-rule-builder.d.ts.map +1 -1
- package/dist/builders/class-rule-builder.js +6 -3
- package/dist/builders/class-rule-builder.js.map +1 -1
- package/dist/builders/function-rule-builder.d.ts +29 -7
- package/dist/builders/function-rule-builder.d.ts.map +1 -1
- package/dist/builders/function-rule-builder.js +34 -8
- package/dist/builders/function-rule-builder.js.map +1 -1
- package/dist/conditions/body-analysis-function.d.ts.map +1 -1
- package/dist/conditions/body-analysis-function.js +19 -1
- package/dist/conditions/body-analysis-function.js.map +1 -1
- package/dist/conditions/body-analysis.d.ts +5 -2
- package/dist/conditions/body-analysis.d.ts.map +1 -1
- package/dist/conditions/body-analysis.js +9 -6
- package/dist/conditions/body-analysis.js.map +1 -1
- package/dist/conditions/call.d.ts +4 -2
- package/dist/conditions/call.d.ts.map +1 -1
- package/dist/conditions/call.js +11 -8
- package/dist/conditions/call.js.map +1 -1
- package/dist/conditions/catch-analysis.d.ts +7 -1
- package/dist/conditions/catch-analysis.d.ts.map +1 -1
- package/dist/conditions/catch-analysis.js +26 -27
- package/dist/conditions/catch-analysis.js.map +1 -1
- package/dist/conditions/class.d.ts +5 -3
- package/dist/conditions/class.d.ts.map +1 -1
- package/dist/conditions/class.js +9 -6
- package/dist/conditions/class.js.map +1 -1
- package/dist/conditions/function.d.ts +4 -4
- package/dist/conditions/function.js +4 -4
- package/dist/core/execute-rule.js +1 -1
- package/dist/graphql/resolver-rule-builder.d.ts.map +1 -1
- package/dist/graphql/resolver-rule-builder.js +16 -2
- package/dist/graphql/resolver-rule-builder.js.map +1 -1
- package/dist/helpers/body-traversal.d.ts +63 -9
- package/dist/helpers/body-traversal.d.ts.map +1 -1
- package/dist/helpers/body-traversal.js +179 -30
- package/dist/helpers/body-traversal.js.map +1 -1
- package/dist/helpers/heritage.d.ts +25 -0
- package/dist/helpers/heritage.d.ts.map +1 -0
- package/dist/helpers/heritage.js +41 -0
- package/dist/helpers/heritage.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/models/arch-function.d.ts +42 -12
- package/dist/models/arch-function.d.ts.map +1 -1
- package/dist/models/arch-function.js +104 -18
- package/dist/models/arch-function.js.map +1 -1
- package/dist/predicates/class.d.ts +9 -9
- package/dist/predicates/class.d.ts.map +1 -1
- package/dist/predicates/class.js +14 -13
- package/dist/predicates/class.js.map +1 -1
- package/dist/predicates/function.d.ts +16 -4
- package/dist/predicates/function.d.ts.map +1 -1
- package/dist/predicates/function.js +56 -3
- package/dist/predicates/function.js.map +1 -1
- package/dist/predicates/type.d.ts +2 -1
- package/dist/predicates/type.d.ts.map +1 -1
- package/dist/predicates/type.js +6 -2
- package/dist/predicates/type.js.map +1 -1
- package/dist/presets/agent-guardrails.js +5 -5
- package/dist/presets/agent-guardrails.js.map +1 -1
- package/dist/rules/code-quality.d.ts +12 -1
- package/dist/rules/code-quality.d.ts.map +1 -1
- package/dist/rules/code-quality.js +106 -12
- package/dist/rules/code-quality.js.map +1 -1
- package/dist/rules/errors.d.ts +4 -2
- package/dist/rules/errors.d.ts.map +1 -1
- package/dist/rules/errors.js +18 -16
- package/dist/rules/errors.js.map +1 -1
- package/dist/rules/hygiene.d.ts +3 -1
- package/dist/rules/hygiene.d.ts.map +1 -1
- package/dist/rules/hygiene.js +3 -1
- package/dist/rules/hygiene.js.map +1 -1
- package/dist/rules/metrics.d.ts +6 -4
- package/dist/rules/metrics.d.ts.map +1 -1
- package/dist/rules/metrics.js +40 -20
- package/dist/rules/metrics.js.map +1 -1
- package/dist/rules/security.d.ts +13 -5
- package/dist/rules/security.d.ts.map +1 -1
- package/dist/rules/security.js +144 -19
- package/dist/rules/security.js.map +1 -1
- package/dist/rules/typescript.d.ts +2 -2
- package/dist/rules/typescript.js +2 -2
- package/dist/smells/duplicate-bodies.js +2 -2
- package/dist/smells/duplicate-bodies.js.map +1 -1
- package/dist/smells/sibling-files.js +2 -2
- package/dist/smells/sibling-files.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"code-quality.d.ts","sourceRoot":"","sources":["../../src/rules/code-quality.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAChD,OAAO,KAAK,EAAE,SAAS,EAAoB,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"code-quality.d.ts","sourceRoot":"","sources":["../../src/rules/code-quality.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAChD,OAAO,KAAK,EAAE,SAAS,EAAoB,MAAM,kBAAkB,CAAA;AAMnE;;;;;;;;;;;;;GAaG;AACH,wBAAgB,2BAA2B,IAAI,SAAS,CAAC,gBAAgB,CAAC,CAuBzE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,cAAc,IAAI,SAAS,CAAC,gBAAgB,CAAC,CAoC5D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,SAAS,CAAC,gBAAgB,CAAC,CAiC5F"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Node, SyntaxKind } from 'ts-morph';
|
|
2
2
|
import { createViolation } from '../core/violation.js';
|
|
3
|
+
import { searchClassBody } from '../helpers/body-traversal.js';
|
|
3
4
|
/**
|
|
4
5
|
* All public methods must have JSDoc comments.
|
|
5
6
|
*
|
|
@@ -82,11 +83,22 @@ export function noPublicFields() {
|
|
|
82
83
|
};
|
|
83
84
|
}
|
|
84
85
|
/**
|
|
85
|
-
*
|
|
86
|
+
* No member code of a class may contain magic numbers: method, constructor and accessor bodies,
|
|
87
|
+
* parameter defaults, property initializers and static blocks (bug 0306). Decorators, computed member
|
|
88
|
+
* names and `extends` are not read: a number in `@Max(150)` or `@Column({ precision: 12 })` is named by the
|
|
89
|
+
* decorator that takes it, and reading them would report every validation and ORM field.
|
|
86
90
|
*
|
|
87
91
|
* Numbers 0, 1, -1, 2, 10, 100 are allowed by default.
|
|
88
92
|
* Configure with options.allowed to customize.
|
|
89
93
|
*
|
|
94
|
+
* A number that is the whole value of one of the class's own properties or its members' parameter
|
|
95
|
+
* defaults, a default inside a destructured parameter included, is named by it, and is not reported
|
|
96
|
+
* — read through a sign, parentheses, `as`, `<T>`,
|
|
97
|
+
* `satisfies` and `!`, so `static readonly LIMIT = 5000 as const` is named too.
|
|
98
|
+
*
|
|
99
|
+
* A finding names the member the number sits in — `Class.method`, `Class.constructor`,
|
|
100
|
+
* `Class.static` for a static block — so a number in a method keeps the message it always had.
|
|
101
|
+
*
|
|
90
102
|
* @example
|
|
91
103
|
* import { noMagicNumbers } from '@nielspeter/eess-ts/rules/code-quality'
|
|
92
104
|
*
|
|
@@ -100,26 +112,108 @@ export function noPublicFields() {
|
|
|
100
112
|
*/
|
|
101
113
|
export function noMagicNumbers(options) {
|
|
102
114
|
const allowedSet = new Set(options?.allowed ?? [0, 1, -1, 2, 10, 100]);
|
|
115
|
+
const magicNumberIn = (cls) => ({
|
|
116
|
+
description: 'magic number',
|
|
117
|
+
syntaxKinds: [SyntaxKind.NumericLiteral],
|
|
118
|
+
matches: (node) => Node.isNumericLiteral(node) &&
|
|
119
|
+
!allowedSet.has(node.getLiteralValue()) &&
|
|
120
|
+
!isNamedValue(node, cls),
|
|
121
|
+
});
|
|
103
122
|
return {
|
|
104
|
-
description: 'have no magic numbers in
|
|
123
|
+
description: 'have no magic numbers in member code',
|
|
105
124
|
evaluate(elements, context) {
|
|
106
125
|
const violations = [];
|
|
107
126
|
for (const cls of elements) {
|
|
108
|
-
for (const
|
|
109
|
-
|
|
110
|
-
if (!
|
|
127
|
+
for (const literal of searchClassBody(cls, magicNumberIn(cls), 'member-code')
|
|
128
|
+
.matchingNodes) {
|
|
129
|
+
if (!Node.isNumericLiteral(literal))
|
|
111
130
|
continue;
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
if (!allowedSet.has(value)) {
|
|
116
|
-
violations.push(createViolation(lit, `${cls.getName() ?? '<anonymous>'}.${method.getName()} contains magic number ${String(value)} — extract to a named constant`, context));
|
|
117
|
-
}
|
|
118
|
-
}
|
|
131
|
+
// The value, not the text: `5_000` is 5000, in the message and against the allowed list.
|
|
132
|
+
const value = literal.getLiteralValue();
|
|
133
|
+
violations.push(createViolation(literal, `${memberLabel(cls, literal)} contains magic number ${String(value)} — extract to a named constant`, context));
|
|
119
134
|
}
|
|
120
135
|
}
|
|
121
136
|
return violations;
|
|
122
137
|
},
|
|
123
138
|
};
|
|
124
139
|
}
|
|
140
|
+
/**
|
|
141
|
+
* A number that is the whole value of one of the class's own declarations — a property's initializer,
|
|
142
|
+
* a member's parameter default, or a binding element's default in a member's destructured parameter
|
|
143
|
+
* (bug 0309) — is named by that declaration: `private timeout = 5000`, `retry(attempts = 3)`,
|
|
144
|
+
* `retry({ attempts = 3 } = {})`, `static readonly LIMIT = -5000 as const`. It is not reported. A
|
|
145
|
+
* number inside a larger initializer or default still is, and so is one in a function or class nested
|
|
146
|
+
* inside a member: the method walk before bug 0306 reported those, and they are not the class's names.
|
|
147
|
+
*/
|
|
148
|
+
function isNamedValue(literal, cls) {
|
|
149
|
+
let value = literal;
|
|
150
|
+
let parent = value.getParent();
|
|
151
|
+
while (parent !== undefined && leavesValueUnchanged(parent)) {
|
|
152
|
+
value = parent;
|
|
153
|
+
parent = value.getParent();
|
|
154
|
+
}
|
|
155
|
+
if (Node.isPropertyDeclaration(parent)) {
|
|
156
|
+
return parent.getInitializer() === value && parent.getParent() === cls;
|
|
157
|
+
}
|
|
158
|
+
if (Node.isParameterDeclaration(parent)) {
|
|
159
|
+
return parent.getInitializer() === value && isOwnParameter(parent, cls);
|
|
160
|
+
}
|
|
161
|
+
if (Node.isBindingElement(parent)) {
|
|
162
|
+
return parent.getInitializer() === value && isOwnParameter(patternOwner(parent), cls);
|
|
163
|
+
}
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
/** Whether a node is a parameter of one of the class's own members, not of a function nested in one. */
|
|
167
|
+
function isOwnParameter(node, cls) {
|
|
168
|
+
return Node.isParameterDeclaration(node) && node.getParent()?.getParent() === cls;
|
|
169
|
+
}
|
|
170
|
+
/** What a binding element destructures, through any nested patterns: a parameter, or a variable. */
|
|
171
|
+
function patternOwner(element) {
|
|
172
|
+
let node = element.getParent();
|
|
173
|
+
while (Node.isObjectBindingPattern(node) ||
|
|
174
|
+
Node.isArrayBindingPattern(node) ||
|
|
175
|
+
Node.isBindingElement(node)) {
|
|
176
|
+
node = node.getParent();
|
|
177
|
+
}
|
|
178
|
+
return node;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* A wrapper that leaves the value inside it unchanged: a `-` or `+` sign, parentheses, `as`, `<T>`,
|
|
182
|
+
* `satisfies` or `!`. The metrics rules read a function-valued property through the same wrappers.
|
|
183
|
+
*/
|
|
184
|
+
function leavesValueUnchanged(node) {
|
|
185
|
+
if (Node.isPrefixUnaryExpression(node)) {
|
|
186
|
+
const operator = node.getOperatorToken();
|
|
187
|
+
return operator === SyntaxKind.MinusToken || operator === SyntaxKind.PlusToken;
|
|
188
|
+
}
|
|
189
|
+
return (Node.isParenthesizedExpression(node) ||
|
|
190
|
+
Node.isAsExpression(node) ||
|
|
191
|
+
Node.isTypeAssertion(node) ||
|
|
192
|
+
Node.isSatisfiesExpression(node) ||
|
|
193
|
+
Node.isNonNullExpression(node));
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* `Class.member` for the member of `cls` a node sits in: `Class.constructor` in a constructor,
|
|
197
|
+
* `Class.static` in a static block, and the class alone for a node outside every member.
|
|
198
|
+
*/
|
|
199
|
+
function memberLabel(cls, node) {
|
|
200
|
+
const className = cls.getName() ?? '<anonymous>';
|
|
201
|
+
let member = node;
|
|
202
|
+
let parent = member.getParent();
|
|
203
|
+
while (parent !== undefined && parent !== cls) {
|
|
204
|
+
member = parent;
|
|
205
|
+
parent = member.getParent();
|
|
206
|
+
}
|
|
207
|
+
if (Node.isConstructorDeclaration(member))
|
|
208
|
+
return `${className}.constructor`;
|
|
209
|
+
if (Node.isClassStaticBlockDeclaration(member))
|
|
210
|
+
return `${className}.static`;
|
|
211
|
+
if (Node.isMethodDeclaration(member) ||
|
|
212
|
+
Node.isPropertyDeclaration(member) ||
|
|
213
|
+
Node.isGetAccessorDeclaration(member) ||
|
|
214
|
+
Node.isSetAccessorDeclaration(member)) {
|
|
215
|
+
return `${className}.${member.getName()}`;
|
|
216
|
+
}
|
|
217
|
+
return className;
|
|
218
|
+
}
|
|
125
219
|
//# sourceMappingURL=code-quality.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"code-quality.js","sourceRoot":"","sources":["../../src/rules/code-quality.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAI3C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"code-quality.js","sourceRoot":"","sources":["../../src/rules/code-quality.ts"],"names":[],"mappings":"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"}
|
package/dist/rules/errors.d.ts
CHANGED
|
@@ -18,8 +18,10 @@ export declare function noTypeErrors(): Condition<ClassDeclaration>;
|
|
|
18
18
|
export declare function functionNoGenericErrors(): Condition<ArchFunction>;
|
|
19
19
|
export declare function functionNoTypeErrors(): Condition<ArchFunction>;
|
|
20
20
|
/**
|
|
21
|
-
* Catch blocks
|
|
22
|
-
*
|
|
21
|
+
* Catch blocks anywhere a class runs code must reference the caught error variable: member
|
|
22
|
+
* bodies, parameter defaults, property initializers (an arrow-function event handler included),
|
|
23
|
+
* static blocks, decorators, computed names and `extends` (bug 0306). It forbids something, so
|
|
24
|
+
* it reads all of it, as `notContain()` on the class builder does.
|
|
23
25
|
*
|
|
24
26
|
* Detects catch blocks that silently discard errors — no logging,
|
|
25
27
|
* no rethrowing, no passing to another function. A common source of
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/rules/errors.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAoB,MAAM,kBAAkB,CAAA;AAGnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/rules/errors.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAoB,MAAM,kBAAkB,CAAA;AAGnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAO9D;;;;;;;;GAQG;AACH,wBAAgB,eAAe,IAAI,SAAS,CAAC,gBAAgB,CAAC,CAE7D;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,SAAS,CAAC,gBAAgB,CAAC,CAE1D;AAID,wBAAgB,uBAAuB,IAAI,SAAS,CAAC,YAAY,CAAC,CAEjE;AAED,wBAAgB,oBAAoB,IAAI,SAAS,CAAC,YAAY,CAAC,CAE9D;AAWD;;;;;;;;;GASG;AACH,wBAAgB,aAAa,IAAI,SAAS,CAAC,gBAAgB,CAAC,CAe3D;AAED,wBAAgB,qBAAqB,IAAI,SAAS,CAAC,YAAY,CAAC,CAe/D;AAED,wBAAgB,mBAAmB,IAAI,SAAS,CAAC,UAAU,CAAC,CAa3D"}
|
package/dist/rules/errors.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { Node } from 'ts-morph';
|
|
1
|
+
import { Node, SyntaxKind } from 'ts-morph';
|
|
2
2
|
import { createViolation } from '../core/violation.js';
|
|
3
3
|
import { newExpr } from '../helpers/matchers.js';
|
|
4
|
+
import { searchClassBody } from '../helpers/body-traversal.js';
|
|
4
5
|
import { classNotContain } from '../conditions/body-analysis.js';
|
|
5
6
|
import { functionNotContain } from '../conditions/body-analysis-function.js';
|
|
6
|
-
import { findSilentCatches } from '../conditions/catch-analysis.js';
|
|
7
|
+
import { findSilentCatches, silentCatchMessage } from '../conditions/catch-analysis.js';
|
|
7
8
|
/**
|
|
8
9
|
* No throwing generic Error — use typed domain errors instead.
|
|
9
10
|
*
|
|
@@ -30,9 +31,17 @@ export function functionNoTypeErrors() {
|
|
|
30
31
|
return functionNotContain(newExpr('TypeError'));
|
|
31
32
|
}
|
|
32
33
|
// ─── Silent catch detection ──────────────────────────────────────
|
|
34
|
+
/** Every catch clause; `noSilentCatch` decides which of them are silent. */
|
|
35
|
+
const catchClause = {
|
|
36
|
+
description: 'catch clause',
|
|
37
|
+
syntaxKinds: [SyntaxKind.CatchClause],
|
|
38
|
+
matches: (node) => Node.isCatchClause(node),
|
|
39
|
+
};
|
|
33
40
|
/**
|
|
34
|
-
* Catch blocks
|
|
35
|
-
*
|
|
41
|
+
* Catch blocks anywhere a class runs code must reference the caught error variable: member
|
|
42
|
+
* bodies, parameter defaults, property initializers (an arrow-function event handler included),
|
|
43
|
+
* static blocks, decorators, computed names and `extends` (bug 0306). It forbids something, so
|
|
44
|
+
* it reads all of it, as `notContain()` on the class builder does.
|
|
36
45
|
*
|
|
37
46
|
* Detects catch blocks that silently discard errors — no logging,
|
|
38
47
|
* no rethrowing, no passing to another function. A common source of
|
|
@@ -44,19 +53,12 @@ export function noSilentCatch() {
|
|
|
44
53
|
evaluate(elements, context) {
|
|
45
54
|
const violations = [];
|
|
46
55
|
for (const cls of elements) {
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
...cls.getConstructors(),
|
|
50
|
-
...cls.getGetAccessors(),
|
|
51
|
-
...cls.getSetAccessors(),
|
|
52
|
-
];
|
|
53
|
-
for (const member of members) {
|
|
54
|
-
const body = member.getBody();
|
|
55
|
-
if (!body)
|
|
56
|
+
for (const node of searchClassBody(cls, catchClause, 'all-code').matchingNodes) {
|
|
57
|
+
if (!Node.isCatchClause(node))
|
|
56
58
|
continue;
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
const message = silentCatchMessage(node);
|
|
60
|
+
if (message !== undefined)
|
|
61
|
+
violations.push(createViolation(node, message, context));
|
|
60
62
|
}
|
|
61
63
|
}
|
|
62
64
|
return violations;
|
package/dist/rules/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/rules/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/rules/errors.ts"],"names":[],"mappings":"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"}
|
package/dist/rules/hygiene.d.ts
CHANGED
|
@@ -42,7 +42,9 @@ export declare function noUnusedExports(): Condition<SourceFile>;
|
|
|
42
42
|
export declare function noStubComments(pattern?: RegExp): Condition<ArchFunction>;
|
|
43
43
|
/**
|
|
44
44
|
* Functions must not have empty bodies.
|
|
45
|
-
* An empty function compiles and passes type checks but does nothing.
|
|
45
|
+
* An empty function compiles and passes type checks but does nothing. An empty constructor whose every
|
|
46
|
+
* parameter is a parameter property, or a private or protected one that takes nothing, does something,
|
|
47
|
+
* and is not reported (bug 0315).
|
|
46
48
|
*
|
|
47
49
|
* @example
|
|
48
50
|
* functions(p)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hygiene.d.ts","sourceRoot":"","sources":["../../src/rules/hygiene.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAC1C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAQ9D;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,IAAI,SAAS,CAAC,UAAU,CAAC,CAErD;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,IAAI,SAAS,CAAC,UAAU,CAAC,CAEvD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,OAAO,GAAE,MAAsB,GAAG,SAAS,CAAC,YAAY,CAAC,CAEvF;AAED
|
|
1
|
+
{"version":3,"file":"hygiene.d.ts","sourceRoot":"","sources":["../../src/rules/hygiene.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAC1C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAQ9D;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,IAAI,SAAS,CAAC,UAAU,CAAC,CAErD;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,IAAI,SAAS,CAAC,UAAU,CAAC,CAEvD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,OAAO,GAAE,MAAsB,GAAG,SAAS,CAAC,YAAY,CAAC,CAEvF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,IAAI,SAAS,CAAC,YAAY,CAAC,CAEvD"}
|
package/dist/rules/hygiene.js
CHANGED
|
@@ -48,7 +48,9 @@ export function noStubComments(pattern = STUB_PATTERNS) {
|
|
|
48
48
|
}
|
|
49
49
|
/**
|
|
50
50
|
* Functions must not have empty bodies.
|
|
51
|
-
* An empty function compiles and passes type checks but does nothing.
|
|
51
|
+
* An empty function compiles and passes type checks but does nothing. An empty constructor whose every
|
|
52
|
+
* parameter is a parameter property, or a private or protected one that takes nothing, does something,
|
|
53
|
+
* and is not reported (bug 0315).
|
|
52
54
|
*
|
|
53
55
|
* @example
|
|
54
56
|
* functions(p)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hygiene.js","sourceRoot":"","sources":["../../src/rules/hygiene.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAC/D,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAA;AACrF,OAAO,EACL,kBAAkB,EAClB,wBAAwB,GACzB,MAAM,yCAAyC,CAAA;AAEhD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,aAAa;IAC3B,OAAO,UAAU,EAAE,CAAA;AACrB,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO,mBAAmB,EAAE,CAAA;AAC9B,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,cAAc,CAAC,UAAkB,aAAa;IAC5D,OAAO,kBAAkB,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAA;AAC7C,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"hygiene.js","sourceRoot":"","sources":["../../src/rules/hygiene.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAC/D,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAA;AACrF,OAAO,EACL,kBAAkB,EAClB,wBAAwB,GACzB,MAAM,yCAAyC,CAAA;AAEhD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,aAAa;IAC3B,OAAO,UAAU,EAAE,CAAA;AACrB,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO,mBAAmB,EAAE,CAAA;AAC9B,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,cAAc,CAAC,UAAkB,aAAa;IAC5D,OAAO,kBAAkB,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAA;AAC7C,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,aAAa;IAC3B,OAAO,wBAAwB,EAAE,CAAA;AACnC,CAAC"}
|
package/dist/rules/metrics.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { ClassDeclaration } from 'ts-morph';
|
|
2
2
|
import type { Condition } from '@nielspeter/eess';
|
|
3
3
|
/**
|
|
4
|
-
* No
|
|
5
|
-
* cyclomatic complexity.
|
|
4
|
+
* No callable member of the class — a method, constructor or accessor, or a property whose
|
|
5
|
+
* value is a function — may exceed the given cyclomatic complexity (bug 0306).
|
|
6
6
|
*
|
|
7
7
|
* @example
|
|
8
8
|
* ```ts
|
|
@@ -25,7 +25,8 @@ export declare function maxCyclomaticComplexity(threshold: number): Condition<Cl
|
|
|
25
25
|
*/
|
|
26
26
|
export declare function maxClassLines(threshold: number): Condition<ClassDeclaration>;
|
|
27
27
|
/**
|
|
28
|
-
* No method
|
|
28
|
+
* No callable member of the class — a method, constructor or accessor, or a property whose
|
|
29
|
+
* value is a function — may exceed the given number of lines (bug 0306).
|
|
29
30
|
*
|
|
30
31
|
* @example
|
|
31
32
|
* ```ts
|
|
@@ -49,7 +50,8 @@ export declare function maxMethodLines(threshold: number): Condition<ClassDeclar
|
|
|
49
50
|
*/
|
|
50
51
|
export declare function maxMethods(threshold: number): Condition<ClassDeclaration>;
|
|
51
52
|
/**
|
|
52
|
-
* No
|
|
53
|
+
* No callable member of the class — a method, constructor or accessor, or a property whose
|
|
54
|
+
* value is a function — may have more than the given number of parameters (bug 0306).
|
|
53
55
|
*
|
|
54
56
|
* @example
|
|
55
57
|
* ```ts
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/rules/metrics.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/rules/metrics.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAChD,OAAO,KAAK,EAAE,SAAS,EAAoB,MAAM,kBAAkB,CAAA;AAkHnE;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC,gBAAgB,CAAC,CAQtF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC,gBAAgB,CAAC,CA2B5E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC,gBAAgB,CAAC,CAU7E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC,gBAAgB,CAAC,CAwBzE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC,gBAAgB,CAAC,CAQ5E;AAGD,OAAO,EACL,qBAAqB,EACrB,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,uBAAuB,CAAA"}
|
package/dist/rules/metrics.js
CHANGED
|
@@ -1,20 +1,38 @@
|
|
|
1
|
+
import { Node } from 'ts-morph';
|
|
1
2
|
import { cyclomaticComplexity, linesOfCode } from '../helpers/complexity.js';
|
|
2
3
|
import { metricViolation } from '../core/metric-violation.js';
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
import { functionValueOf } from '../models/arch-function.js';
|
|
5
|
+
function callableMembers(cls) {
|
|
6
|
+
const clsName = cls.getName() ?? '<anonymous>';
|
|
7
|
+
const members = [];
|
|
8
|
+
for (const member of [
|
|
5
9
|
...cls.getMethods(),
|
|
6
10
|
...cls.getConstructors(),
|
|
7
11
|
...cls.getGetAccessors(),
|
|
8
12
|
...cls.getSetAccessors(),
|
|
9
|
-
]
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
]) {
|
|
14
|
+
members.push({
|
|
15
|
+
node: member,
|
|
16
|
+
name: Node.isConstructorDeclaration(member)
|
|
17
|
+
? `${clsName}.constructor`
|
|
18
|
+
: `${clsName}.${member.getName()}`,
|
|
19
|
+
body: member.getBody(),
|
|
20
|
+
parameterCount: member.getParameters().length,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
// After the declared members, so a finding the old walk reported keeps its place.
|
|
24
|
+
for (const property of cls.getProperties()) {
|
|
25
|
+
const value = functionValueOf(property.getInitializer());
|
|
26
|
+
if (value === undefined)
|
|
27
|
+
continue;
|
|
28
|
+
members.push({
|
|
29
|
+
node: property,
|
|
30
|
+
name: `${clsName}.${property.getName()}`,
|
|
31
|
+
body: value.getBody(),
|
|
32
|
+
parameterCount: value.getParameters().length,
|
|
33
|
+
});
|
|
16
34
|
}
|
|
17
|
-
return
|
|
35
|
+
return members;
|
|
18
36
|
}
|
|
19
37
|
/**
|
|
20
38
|
* A ceiling on one measurement of every callable member of every class.
|
|
@@ -37,12 +55,12 @@ function memberCeiling(threshold, spec) {
|
|
|
37
55
|
evaluate(elements, context) {
|
|
38
56
|
const violations = [];
|
|
39
57
|
for (const cls of elements) {
|
|
40
|
-
for (const member of
|
|
58
|
+
for (const member of callableMembers(cls)) {
|
|
41
59
|
const value = spec.measure(member);
|
|
42
60
|
if (value <= threshold)
|
|
43
61
|
continue;
|
|
44
|
-
const name =
|
|
45
|
-
violations.push(metricViolation(member, {
|
|
62
|
+
const name = member.name;
|
|
63
|
+
violations.push(metricViolation(member.node, {
|
|
46
64
|
metric: spec.metric,
|
|
47
65
|
...(spec.unit === undefined ? {} : { unit: spec.unit }),
|
|
48
66
|
// Written long-hand deliberately: `measured,` is a
|
|
@@ -62,8 +80,8 @@ function memberCeiling(threshold, spec) {
|
|
|
62
80
|
};
|
|
63
81
|
}
|
|
64
82
|
/**
|
|
65
|
-
* No
|
|
66
|
-
* cyclomatic complexity.
|
|
83
|
+
* No callable member of the class — a method, constructor or accessor, or a property whose
|
|
84
|
+
* value is a function — may exceed the given cyclomatic complexity (bug 0306).
|
|
67
85
|
*
|
|
68
86
|
* @example
|
|
69
87
|
* ```ts
|
|
@@ -76,7 +94,7 @@ export function maxCyclomaticComplexity(threshold) {
|
|
|
76
94
|
return memberCeiling(threshold, {
|
|
77
95
|
description: `have no method with cyclomatic complexity > ${String(threshold)}`,
|
|
78
96
|
metric: 'complexity',
|
|
79
|
-
measure: (member) => cyclomaticComplexity(member.
|
|
97
|
+
measure: (member) => cyclomaticComplexity(member.body),
|
|
80
98
|
message: (name, cc) => `${name} has cyclomatic complexity ${String(cc)} (max: ${String(threshold)}) — split into smaller methods`,
|
|
81
99
|
});
|
|
82
100
|
}
|
|
@@ -114,7 +132,8 @@ export function maxClassLines(threshold) {
|
|
|
114
132
|
};
|
|
115
133
|
}
|
|
116
134
|
/**
|
|
117
|
-
* No method
|
|
135
|
+
* No callable member of the class — a method, constructor or accessor, or a property whose
|
|
136
|
+
* value is a function — may exceed the given number of lines (bug 0306).
|
|
118
137
|
*
|
|
119
138
|
* @example
|
|
120
139
|
* ```ts
|
|
@@ -130,7 +149,7 @@ export function maxMethodLines(threshold) {
|
|
|
130
149
|
// `code-lines` since bug 0170 — the metric kept its name when it stopped
|
|
131
150
|
// counting comments, and the baseline must not compare across that.
|
|
132
151
|
unit: 'code-lines',
|
|
133
|
-
measure: (member) => linesOfCode(member),
|
|
152
|
+
measure: (member) => linesOfCode(member.node),
|
|
134
153
|
message: (name, loc) => `${name} has ${String(loc)} code lines (max: ${String(threshold)})`,
|
|
135
154
|
});
|
|
136
155
|
}
|
|
@@ -166,7 +185,8 @@ export function maxMethods(threshold) {
|
|
|
166
185
|
};
|
|
167
186
|
}
|
|
168
187
|
/**
|
|
169
|
-
* No
|
|
188
|
+
* No callable member of the class — a method, constructor or accessor, or a property whose
|
|
189
|
+
* value is a function — may have more than the given number of parameters (bug 0306).
|
|
170
190
|
*
|
|
171
191
|
* @example
|
|
172
192
|
* ```ts
|
|
@@ -181,7 +201,7 @@ export function maxParameters(threshold) {
|
|
|
181
201
|
return memberCeiling(threshold, {
|
|
182
202
|
description: `have no method with more than ${String(threshold)} parameters`,
|
|
183
203
|
metric: 'parameters',
|
|
184
|
-
measure: (member) => member.
|
|
204
|
+
measure: (member) => member.parameterCount,
|
|
185
205
|
message: (name, params) => `${name} has ${String(params)} parameters (max: ${String(threshold)}) — use an options object`,
|
|
186
206
|
});
|
|
187
207
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../src/rules/metrics.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../src/rules/metrics.ts"],"names":[],"mappings":"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"}
|
package/dist/rules/security.d.ts
CHANGED
|
@@ -2,21 +2,27 @@ import type { ClassDeclaration, SourceFile } from 'ts-morph';
|
|
|
2
2
|
import type { Condition } from '@nielspeter/eess';
|
|
3
3
|
import type { ArchFunction } from '../models/arch-function.js';
|
|
4
4
|
/**
|
|
5
|
-
* No eval() calls in class
|
|
5
|
+
* No eval() calls in any code a class runs — `eval(…)`, through a global object
|
|
6
|
+
* (`globalThis`, `window`, `self`, `global`), a string-keyed bracket, or the indirect
|
|
7
|
+
* `(0, eval)(…)`. An `eval` bound to a local name first is not seen (bug 0305).
|
|
6
8
|
*
|
|
7
9
|
* @example
|
|
8
10
|
* classes(p).should().satisfy(noEval()).check()
|
|
9
11
|
*/
|
|
10
12
|
export declare function noEval(): Condition<ClassDeclaration>;
|
|
11
13
|
/**
|
|
12
|
-
* No
|
|
14
|
+
* No Function constructor (equivalent to eval) — called with or without `new`, and
|
|
15
|
+
* through a global object.
|
|
13
16
|
*
|
|
14
17
|
* @example
|
|
15
18
|
* classes(p).should().satisfy(noFunctionConstructor()).check()
|
|
16
19
|
*/
|
|
17
20
|
export declare function noFunctionConstructor(): Condition<ClassDeclaration>;
|
|
18
21
|
/**
|
|
19
|
-
* No
|
|
22
|
+
* No process.env read in any code a class runs, as `notContain()` on the class
|
|
23
|
+
* builder defines it, spelled `process.env`, `process['env']`, or through a
|
|
24
|
+
* global object. An `env` destructured from `process` or imported from `node:process` is
|
|
25
|
+
* not seen (bug 0305); `import.meta.env` is not Node's environment and is not reported.
|
|
20
26
|
*
|
|
21
27
|
* Use dependency injection for configuration instead.
|
|
22
28
|
*
|
|
@@ -28,7 +34,8 @@ export declare function noFunctionConstructor(): Condition<ClassDeclaration>;
|
|
|
28
34
|
*/
|
|
29
35
|
export declare function noProcessEnv(): Condition<ClassDeclaration>;
|
|
30
36
|
/**
|
|
31
|
-
* No console.log calls in class
|
|
37
|
+
* No console.log calls in any code a class runs — including `console['log']` and through a
|
|
38
|
+
* global object.
|
|
32
39
|
*
|
|
33
40
|
* Use a logger abstraction instead.
|
|
34
41
|
*
|
|
@@ -39,7 +46,8 @@ export declare function noProcessEnv(): Condition<ClassDeclaration>;
|
|
|
39
46
|
*/
|
|
40
47
|
export declare function noConsoleLog(): Condition<ClassDeclaration>;
|
|
41
48
|
/**
|
|
42
|
-
* No direct console access (any method: log, warn, error, debug, info)
|
|
49
|
+
* No direct console access (any method: log, warn, error, debug, info), including
|
|
50
|
+
* bracketed and global-object spellings.
|
|
43
51
|
* Stricter than noConsoleLog — catches all console methods.
|
|
44
52
|
*/
|
|
45
53
|
export declare function noConsole(): Condition<ClassDeclaration>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../../src/rules/security.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../../src/rules/security.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAmI9D;;;;;;;GAOG;AACH,wBAAgB,MAAM,IAAI,SAAS,CAAC,gBAAgB,CAAC,CAEpD;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,IAAI,SAAS,CAAC,gBAAgB,CAAC,CAEnE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,IAAI,SAAS,CAAC,gBAAgB,CAAC,CAE1D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,IAAI,SAAS,CAAC,gBAAgB,CAAC,CAE1D;AAED;;;;GAIG;AACH,wBAAgB,SAAS,IAAI,SAAS,CAAC,gBAAgB,CAAC,CAEvD;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,SAAS,CAAC,gBAAgB,CAAC,CAEzD;AAID,wBAAgB,cAAc,IAAI,SAAS,CAAC,YAAY,CAAC,CAExD;AAED,wBAAgB,6BAA6B,IAAI,SAAS,CAAC,YAAY,CAAC,CAEvE;AAED,wBAAgB,oBAAoB,IAAI,SAAS,CAAC,YAAY,CAAC,CAE9D;AAED,wBAAgB,oBAAoB,IAAI,SAAS,CAAC,YAAY,CAAC,CAE9D;AAED,wBAAgB,iBAAiB,IAAI,SAAS,CAAC,YAAY,CAAC,CAE3D;AAED,wBAAgB,mBAAmB,IAAI,SAAS,CAAC,YAAY,CAAC,CAE7D;AAID,wBAAgB,YAAY,IAAI,SAAS,CAAC,UAAU,CAAC,CAEpD;AAED,wBAAgB,kBAAkB,IAAI,SAAS,CAAC,UAAU,CAAC,CAE1D;AAED,wBAAgB,kBAAkB,IAAI,SAAS,CAAC,UAAU,CAAC,CAE1D"}
|