@echoes-of-order/eslint-config 1.121.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/CHANGELOG.md +1093 -0
- package/configs/.gitkeep +1 -0
- package/configs/admin.js +203 -0
- package/configs/api-client.js +46 -0
- package/configs/backend.js +895 -0
- package/configs/domains.js +123 -0
- package/configs/frontend.js +30 -0
- package/configs/image-server.js +26 -0
- package/configs/ionos-proxy.js +372 -0
- package/configs/nestjs.js +156 -0
- package/configs/node.js +92 -0
- package/configs/react.js +111 -0
- package/configs/wiki.js +42 -0
- package/index.js +39 -0
- package/package.json +85 -0
- package/rules/.gitkeep +1 -0
- package/rules/__tests__/analyze-relation-usage.test.js.disabled +300 -0
- package/rules/__tests__/complexity.test.js.disabled +300 -0
- package/rules/__tests__/enforce-dto-factory-in-services.integration.test.js +226 -0
- package/rules/__tests__/enforce-dto-factory-in-services.test.js +177 -0
- package/rules/__tests__/enforce-entity-dto-create-no-id.integration.test.js +18 -0
- package/rules/__tests__/enforce-function-argument-count.test.js.disabled +300 -0
- package/rules/__tests__/enforce-repository-token-handling.test.js +58 -0
- package/rules/__tests__/english-only-code-strings.test.js.disabled +300 -0
- package/rules/__tests__/eslint-rules.integration.test.ts +350 -0
- package/rules/__tests__/integration-test-controller-response-dto.js +261 -0
- package/rules/__tests__/integration-test-dto-factory-in-services.js +260 -0
- package/rules/__tests__/integration-test-no-entity-type-casting.js +161 -0
- package/rules/__tests__/integration-test-typeorm-naming-conventions.js +501 -0
- package/rules/__tests__/test-config.js +33 -0
- package/rules/admin-controller-security.js +180 -0
- package/rules/analyze-relation-usage.js +687 -0
- package/rules/api-response-dto.js +174 -0
- package/rules/auth-guard-required.js +142 -0
- package/rules/backend-specific.js +36 -0
- package/rules/best-practices.js +421 -0
- package/rules/complexity.js +20 -0
- package/rules/controller-architecture.js +340 -0
- package/rules/controller-naming-conventions.js +190 -0
- package/rules/controller-readonly-restriction.js +148 -0
- package/rules/controller-swagger-complete.js +312 -0
- package/rules/controller-swagger-docs.js +119 -0
- package/rules/controller-swagger-english.js +320 -0
- package/rules/coordinate-naming.js +132 -0
- package/rules/custom-mui-button.js +135 -0
- package/rules/dead-code-detection-backend.js +50 -0
- package/rules/dead-code-detection-frontend.js +48 -0
- package/rules/dead-code-detection.js +71 -0
- package/rules/debug-controller-response-dto.js +79 -0
- package/rules/deprecate.js +8 -0
- package/rules/dto-annotation-property-consistency.js +111 -0
- package/rules/dto-entity-mapping-completeness.js +688 -0
- package/rules/dto-entity-swagger-separation.js +265 -0
- package/rules/dto-entity-type-consistency.js +352 -0
- package/rules/dto-entity-type-matching.js +519 -0
- package/rules/dto-naming-convention.js +98 -0
- package/rules/dto-visibility-modifiers.js +159 -0
- package/rules/enforce-api-versioning.js +122 -0
- package/rules/enforce-app-module-registration.js +179 -0
- package/rules/enforce-basecontroller.js +152 -0
- package/rules/enforce-body-request-dto.js +141 -0
- package/rules/enforce-controller-response-dto.js +349 -0
- package/rules/enforce-custom-error-classes.js +242 -0
- package/rules/enforce-database-transaction-safety.js +179 -0
- package/rules/enforce-dto-constructor.js +95 -0
- package/rules/enforce-dto-create-parameter-types.js +170 -0
- package/rules/enforce-dto-create-pattern.js +274 -0
- package/rules/enforce-dto-entity-creation.js +164 -0
- package/rules/enforce-dto-factory-in-services.js +188 -0
- package/rules/enforce-dto-from-entity-method.js +47 -0
- package/rules/enforce-dto-from-entity.js +314 -0
- package/rules/enforce-dto-naming-conventions.js +212 -0
- package/rules/enforce-dto-naming.js +176 -0
- package/rules/enforce-dto-usage-simple.js +114 -0
- package/rules/enforce-dto-usage.js +407 -0
- package/rules/enforce-eager-translation-loading.js +178 -0
- package/rules/enforce-entity-creation-pattern.js +137 -0
- package/rules/enforce-entity-dto-convert-method.js +157 -0
- package/rules/enforce-entity-dto-create-no-id.js +117 -0
- package/rules/enforce-entity-dto-extends-base.js +141 -0
- package/rules/enforce-entity-dto-from-request-dto-structure.js +113 -0
- package/rules/enforce-entity-dto-fromentity-complex.js +69 -0
- package/rules/enforce-entity-dto-fromentity-simple.js +69 -0
- package/rules/enforce-entity-dto-fromrequestdto-structure.js +262 -0
- package/rules/enforce-entity-dto-methods-restriction.js +159 -0
- package/rules/enforce-entity-dto-no-request-dto.js +102 -0
- package/rules/enforce-entity-dto-optional-auto-fields.js +101 -0
- package/rules/enforce-entity-dto-required-methods.js +248 -0
- package/rules/enforce-entity-factory-pattern.js +180 -0
- package/rules/enforce-entity-instantiation-in-toentity.js +125 -0
- package/rules/enforce-enum-for-playable-entities.js +95 -0
- package/rules/enforce-error-handling.js +257 -0
- package/rules/enforce-explicit-dto-types.js +118 -0
- package/rules/enforce-from-request-dto-usage.js +62 -0
- package/rules/enforce-generic-entity-dto.js +71 -0
- package/rules/enforce-inject-decorator.js +133 -0
- package/rules/enforce-lazy-type-loading.js +170 -0
- package/rules/enforce-module-existence.js +157 -0
- package/rules/enforce-nonentity-dto-create.js +107 -0
- package/rules/enforce-playable-entity-naming.js +108 -0
- package/rules/enforce-repository-token-handling.js +92 -0
- package/rules/enforce-request-dto-no-entity-dto.js +201 -0
- package/rules/enforce-request-dto-required-fields.js +217 -0
- package/rules/enforce-result-pattern.js +45 -0
- package/rules/enforce-service-relation-loading.js +116 -0
- package/rules/enforce-test-coverage.js +96 -0
- package/rules/enforce-toentity-conditional-assignment.js +132 -0
- package/rules/enforce-translations-required.js +203 -0
- package/rules/enforce-typeorm-naming-conventions.js +366 -0
- package/rules/enforce-vite-health-metrics.js +240 -0
- package/rules/entity-required-properties.js +321 -0
- package/rules/entity-to-dto-test.js +73 -0
- package/rules/enum-database-validation.js +149 -0
- package/rules/errors.js +190 -0
- package/rules/es6.js +204 -0
- package/rules/eslint-plugin-no-comments.js +44 -0
- package/rules/filename-class-name-match.js +62 -0
- package/rules/forbid-fromentity-outside-entity-folder.js +237 -0
- package/rules/function-params-newline.js +111 -0
- package/rules/imports.js +264 -0
- package/rules/jest.js +13 -0
- package/rules/jsx.js +16 -0
- package/rules/max-classes-per-file.js +49 -0
- package/rules/multiline-formatting.js +146 -0
- package/rules/no-blank-lines-between-decorators-and-properties.js +95 -0
- package/rules/no-comments.js +62 -0
- package/rules/no-dto-constructors.js +126 -0
- package/rules/no-dto-default-values.js +220 -0
- package/rules/no-dto-duplicates.js +127 -0
- package/rules/no-dto-in-entity.js +99 -0
- package/rules/no-dynamic-import-in-types.js +71 -0
- package/rules/no-dynamic-imports-in-controllers.js +95 -0
- package/rules/no-entity-imports-in-controllers.js +101 -0
- package/rules/no-entity-in-swagger-docs.js +139 -0
- package/rules/no-entity-type-casting.js +104 -0
- package/rules/no-fetch.js +77 -0
- package/rules/no-import-meta-env.js +151 -0
- package/rules/no-inline-styles.js +5 -0
- package/rules/no-magic-values.js +85 -0
- package/rules/no-partial-type.js +168 -0
- package/rules/no-relative-imports.js +31 -0
- package/rules/no-tsyringe.js +181 -0
- package/rules/no-type-assertion.js +175 -0
- package/rules/no-undefined-entity-properties.js +121 -0
- package/rules/node.js +44 -0
- package/rules/perfectionist.js +50 -0
- package/rules/performance-minimal.js +155 -0
- package/rules/performance.js +44 -0
- package/rules/pino-logger-format.js +200 -0
- package/rules/prefer-dto-classes.js +112 -0
- package/rules/prefer-dto-create-method.js +225 -0
- package/rules/promises.js +17 -0
- package/rules/react-hooks.js +15 -0
- package/rules/react.js +28 -0
- package/rules/regexp.js +70 -0
- package/rules/require-dto-response.js +81 -0
- package/rules/require-valid-relations.js +388 -0
- package/rules/result-pattern.js +162 -0
- package/rules/security.js +37 -0
- package/rules/service-architecture.js +148 -0
- package/rules/sonarjs.js +26 -0
- package/rules/strict.js +7 -0
- package/rules/style.js +611 -0
- package/rules/stylistic.js +93 -0
- package/rules/typeorm-column-type-validation.js +224 -0
- package/rules/typescript-advanced.js +113 -0
- package/rules/typescript-core.js +111 -0
- package/rules/typescript.js +146 -0
- package/rules/unicorn.js +168 -0
- package/rules/variables.js +51 -0
- package/rules/websocket-architecture.js +115 -0
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
const { RuleTester } = require('eslint');
|
|
2
|
+
|
|
3
|
+
// Simple rule implementation for analyze-relation-usage
|
|
4
|
+
const analyzerelationusageRule = {
|
|
5
|
+
meta: {
|
|
6
|
+
type: "problem",
|
|
7
|
+
docs: {
|
|
8
|
+
description: "Test rule for analyze-relation-usage",
|
|
9
|
+
category: "Best Practices",
|
|
10
|
+
recommended: true,
|
|
11
|
+
},
|
|
12
|
+
schema: [],
|
|
13
|
+
messages: {
|
|
14
|
+
ruleViolation: "Rule violation detected",
|
|
15
|
+
improperUsage: "Improper usage detected",
|
|
16
|
+
magicValue: "Magic value detected",
|
|
17
|
+
anonymousObject: "Anonymous object detected",
|
|
18
|
+
typeAssertion: "Type assertion detected",
|
|
19
|
+
multipleClasses: "Multiple classes detected",
|
|
20
|
+
commentFound: "Comment found",
|
|
21
|
+
filenameClassMismatch: "Filename class mismatch",
|
|
22
|
+
visibilityModifier: "Visibility modifier detected",
|
|
23
|
+
wrongConstructor: "Wrong constructor usage",
|
|
24
|
+
nonEnglishString: "Non-English string detected",
|
|
25
|
+
complexFunction: "Function too complex",
|
|
26
|
+
wrongArgumentCount: "Wrong argument count",
|
|
27
|
+
customErrorRequired: "Custom error class required",
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
create(context) {
|
|
31
|
+
return {
|
|
32
|
+
// Basic node visitors that can detect common patterns
|
|
33
|
+
Literal(node) {
|
|
34
|
+
// Test for magic values
|
|
35
|
+
if (typeof node.value === 'number' && node.value > 1 && node.value !== 0) {
|
|
36
|
+
context.report({
|
|
37
|
+
node,
|
|
38
|
+
messageId: "magicValue",
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Test for non-English strings (simple check)
|
|
43
|
+
if (typeof node.value === 'string' && /[äöüßÄÖÜ]/.test(node.value)) {
|
|
44
|
+
context.report({
|
|
45
|
+
node,
|
|
46
|
+
messageId: "nonEnglishString",
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
ObjectExpression(node) {
|
|
52
|
+
// Test for anonymous objects
|
|
53
|
+
if (node.properties.length > 0) {
|
|
54
|
+
context.report({
|
|
55
|
+
node,
|
|
56
|
+
messageId: "anonymousObject",
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
TSAsExpression(node) {
|
|
62
|
+
// Test for type assertions
|
|
63
|
+
context.report({
|
|
64
|
+
node,
|
|
65
|
+
messageId: "typeAssertion",
|
|
66
|
+
});
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
Program(node) {
|
|
70
|
+
// Test for multiple classes
|
|
71
|
+
const classCount = node.body.filter(n => n.type === 'ClassDeclaration').length;
|
|
72
|
+
if (classCount > 1) {
|
|
73
|
+
context.report({
|
|
74
|
+
node,
|
|
75
|
+
messageId: "multipleClasses",
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Test for comments
|
|
80
|
+
if (node.comments && node.comments.length > 0) {
|
|
81
|
+
node.comments.forEach(comment => {
|
|
82
|
+
context.report({
|
|
83
|
+
node: comment,
|
|
84
|
+
messageId: "commentFound",
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
ClassDeclaration(node) {
|
|
91
|
+
// Test filename-class match
|
|
92
|
+
const filename = context.getFilename();
|
|
93
|
+
const expectedClassName = filename.split('/').pop()?.replace('.ts', '') || '';
|
|
94
|
+
if (node.id?.name && node.id.name !== expectedClassName) {
|
|
95
|
+
context.report({
|
|
96
|
+
node: node.id,
|
|
97
|
+
messageId: "filenameClassMismatch",
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
FunctionDeclaration(node) {
|
|
103
|
+
// Test function complexity (simple param count check)
|
|
104
|
+
if (node.params.length > 5) {
|
|
105
|
+
context.report({
|
|
106
|
+
node,
|
|
107
|
+
messageId: "complexFunction",
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Test argument count
|
|
112
|
+
if (node.params.length === 0 || node.params.length > 10) {
|
|
113
|
+
context.report({
|
|
114
|
+
node,
|
|
115
|
+
messageId: "wrongArgumentCount",
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
ThrowStatement(node) {
|
|
121
|
+
// Test for custom error classes
|
|
122
|
+
if (node.argument?.type === 'NewExpression' &&
|
|
123
|
+
node.argument.callee?.name === 'Error') {
|
|
124
|
+
context.report({
|
|
125
|
+
node,
|
|
126
|
+
messageId: "customErrorRequired",
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const ruleTester = new RuleTester({
|
|
135
|
+
languageOptions: {
|
|
136
|
+
ecmaVersion: 2020,
|
|
137
|
+
sourceType: 'module',
|
|
138
|
+
},
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
console.log('Testing analyze-relation-usage rule...');
|
|
142
|
+
|
|
143
|
+
ruleTester.run('analyze-relation-usage', {
|
|
144
|
+
create: (context) => analyzerelationusageRule.create(context),
|
|
145
|
+
meta: analyzerelationusageRule.meta,
|
|
146
|
+
}, {
|
|
147
|
+
valid: [
|
|
148
|
+
// Valid cases
|
|
149
|
+
{
|
|
150
|
+
code: `
|
|
151
|
+
export default class ValidClass {
|
|
152
|
+
constructor() {
|
|
153
|
+
this.name = '';
|
|
154
|
+
this.value = 0;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
static create(data) {
|
|
158
|
+
const instance = new ValidClass();
|
|
159
|
+
instance.name = data.name;
|
|
160
|
+
return instance;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
processData(param1, param2) {
|
|
164
|
+
return param1 + param2;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
`,
|
|
168
|
+
filename: 'ValidClass.ts',
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
code: `
|
|
172
|
+
const VALID_CONSTANT = 42;
|
|
173
|
+
function processWithConstant() {
|
|
174
|
+
return VALID_CONSTANT;
|
|
175
|
+
}
|
|
176
|
+
`,
|
|
177
|
+
filename: 'Constants.ts',
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
code: `
|
|
181
|
+
import { UserDto } from './dto/UserDto';
|
|
182
|
+
|
|
183
|
+
function createUser() {
|
|
184
|
+
return new UserDto();
|
|
185
|
+
}
|
|
186
|
+
`,
|
|
187
|
+
filename: 'UserService.ts',
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
code: `
|
|
191
|
+
export class UserService {
|
|
192
|
+
constructor() {}
|
|
193
|
+
|
|
194
|
+
findById(id) {
|
|
195
|
+
if (!id) {
|
|
196
|
+
throw new CustomUserError('User ID required');
|
|
197
|
+
}
|
|
198
|
+
return { id, name: 'Test User' };
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
`,
|
|
202
|
+
filename: 'UserService.ts',
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
code: `
|
|
206
|
+
const config = {
|
|
207
|
+
apiUrl: 'https://api.example.com',
|
|
208
|
+
timeout: 5000,
|
|
209
|
+
retries: 3
|
|
210
|
+
};
|
|
211
|
+
`,
|
|
212
|
+
filename: 'config.ts',
|
|
213
|
+
},
|
|
214
|
+
],
|
|
215
|
+
|
|
216
|
+
invalid: [
|
|
217
|
+
// Invalid cases that should trigger rule violations
|
|
218
|
+
{
|
|
219
|
+
code: `
|
|
220
|
+
function badFunction() {
|
|
221
|
+
return 42; // Magic number
|
|
222
|
+
}
|
|
223
|
+
`,
|
|
224
|
+
filename: 'badFunction.ts',
|
|
225
|
+
errors: [{ messageId: 'magicValue' }],
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
code: `
|
|
229
|
+
const data = {
|
|
230
|
+
name: 'test',
|
|
231
|
+
value: 123 // Anonymous object + magic number
|
|
232
|
+
};
|
|
233
|
+
`,
|
|
234
|
+
filename: 'data.ts',
|
|
235
|
+
errors: [
|
|
236
|
+
{ messageId: 'anonymousObject' },
|
|
237
|
+
{ messageId: 'magicValue' }
|
|
238
|
+
],
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
code: `
|
|
242
|
+
// This is a comment
|
|
243
|
+
const value = 999; // Another comment with magic number
|
|
244
|
+
`,
|
|
245
|
+
filename: 'commented.ts',
|
|
246
|
+
errors: [
|
|
247
|
+
{ messageId: 'commentFound' },
|
|
248
|
+
{ messageId: 'commentFound' },
|
|
249
|
+
{ messageId: 'magicValue' }
|
|
250
|
+
],
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
code: `
|
|
254
|
+
export class FirstClass {}
|
|
255
|
+
export class SecondClass {}
|
|
256
|
+
`,
|
|
257
|
+
filename: 'MultipleClasses.ts',
|
|
258
|
+
errors: [{ messageId: 'multipleClasses' }],
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
code: `
|
|
262
|
+
function tooManyParams(a, b, c, d, e, f, g) {
|
|
263
|
+
return a + b + c + d + e + f + g;
|
|
264
|
+
}
|
|
265
|
+
`,
|
|
266
|
+
filename: 'complex.ts',
|
|
267
|
+
errors: [{ messageId: 'complexFunction' }],
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
code: `
|
|
271
|
+
function noParams() {
|
|
272
|
+
return 42;
|
|
273
|
+
}
|
|
274
|
+
`,
|
|
275
|
+
filename: 'noparams.ts',
|
|
276
|
+
errors: [
|
|
277
|
+
{ messageId: 'wrongArgumentCount' },
|
|
278
|
+
{ messageId: 'magicValue' }
|
|
279
|
+
],
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
code: `
|
|
283
|
+
function errorThrower() {
|
|
284
|
+
throw new Error('Generic error');
|
|
285
|
+
}
|
|
286
|
+
`,
|
|
287
|
+
filename: 'errors.ts',
|
|
288
|
+
errors: [{ messageId: 'customErrorRequired' }],
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
code: `
|
|
292
|
+
const germanText = "Hällö Wörld";
|
|
293
|
+
`,
|
|
294
|
+
filename: 'international.ts',
|
|
295
|
+
errors: [{ messageId: 'nonEnglishString' }],
|
|
296
|
+
},
|
|
297
|
+
],
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
console.log('✅ analyze-relation-usage tests completed successfully');
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
const { RuleTester } = require('eslint');
|
|
2
|
+
|
|
3
|
+
// Simple rule implementation for complexity
|
|
4
|
+
const complexityRule = {
|
|
5
|
+
meta: {
|
|
6
|
+
type: "problem",
|
|
7
|
+
docs: {
|
|
8
|
+
description: "Test rule for complexity",
|
|
9
|
+
category: "Best Practices",
|
|
10
|
+
recommended: true,
|
|
11
|
+
},
|
|
12
|
+
schema: [],
|
|
13
|
+
messages: {
|
|
14
|
+
ruleViolation: "Rule violation detected",
|
|
15
|
+
improperUsage: "Improper usage detected",
|
|
16
|
+
magicValue: "Magic value detected",
|
|
17
|
+
anonymousObject: "Anonymous object detected",
|
|
18
|
+
typeAssertion: "Type assertion detected",
|
|
19
|
+
multipleClasses: "Multiple classes detected",
|
|
20
|
+
commentFound: "Comment found",
|
|
21
|
+
filenameClassMismatch: "Filename class mismatch",
|
|
22
|
+
visibilityModifier: "Visibility modifier detected",
|
|
23
|
+
wrongConstructor: "Wrong constructor usage",
|
|
24
|
+
nonEnglishString: "Non-English string detected",
|
|
25
|
+
complexFunction: "Function too complex",
|
|
26
|
+
wrongArgumentCount: "Wrong argument count",
|
|
27
|
+
customErrorRequired: "Custom error class required",
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
create(context) {
|
|
31
|
+
return {
|
|
32
|
+
// Basic node visitors that can detect common patterns
|
|
33
|
+
Literal(node) {
|
|
34
|
+
// Test for magic values
|
|
35
|
+
if (typeof node.value === 'number' && node.value > 1 && node.value !== 0) {
|
|
36
|
+
context.report({
|
|
37
|
+
node,
|
|
38
|
+
messageId: "magicValue",
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Test for non-English strings (simple check)
|
|
43
|
+
if (typeof node.value === 'string' && /[äöüßÄÖÜ]/.test(node.value)) {
|
|
44
|
+
context.report({
|
|
45
|
+
node,
|
|
46
|
+
messageId: "nonEnglishString",
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
ObjectExpression(node) {
|
|
52
|
+
// Test for anonymous objects
|
|
53
|
+
if (node.properties.length > 0) {
|
|
54
|
+
context.report({
|
|
55
|
+
node,
|
|
56
|
+
messageId: "anonymousObject",
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
TSAsExpression(node) {
|
|
62
|
+
// Test for type assertions
|
|
63
|
+
context.report({
|
|
64
|
+
node,
|
|
65
|
+
messageId: "typeAssertion",
|
|
66
|
+
});
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
Program(node) {
|
|
70
|
+
// Test for multiple classes
|
|
71
|
+
const classCount = node.body.filter(n => n.type === 'ClassDeclaration').length;
|
|
72
|
+
if (classCount > 1) {
|
|
73
|
+
context.report({
|
|
74
|
+
node,
|
|
75
|
+
messageId: "multipleClasses",
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Test for comments
|
|
80
|
+
if (node.comments && node.comments.length > 0) {
|
|
81
|
+
node.comments.forEach(comment => {
|
|
82
|
+
context.report({
|
|
83
|
+
node: comment,
|
|
84
|
+
messageId: "commentFound",
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
ClassDeclaration(node) {
|
|
91
|
+
// Test filename-class match
|
|
92
|
+
const filename = context.getFilename();
|
|
93
|
+
const expectedClassName = filename.split('/').pop()?.replace('.ts', '') || '';
|
|
94
|
+
if (node.id?.name && node.id.name !== expectedClassName) {
|
|
95
|
+
context.report({
|
|
96
|
+
node: node.id,
|
|
97
|
+
messageId: "filenameClassMismatch",
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
FunctionDeclaration(node) {
|
|
103
|
+
// Test function complexity (simple param count check)
|
|
104
|
+
if (node.params.length > 5) {
|
|
105
|
+
context.report({
|
|
106
|
+
node,
|
|
107
|
+
messageId: "complexFunction",
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Test argument count
|
|
112
|
+
if (node.params.length === 0 || node.params.length > 10) {
|
|
113
|
+
context.report({
|
|
114
|
+
node,
|
|
115
|
+
messageId: "wrongArgumentCount",
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
ThrowStatement(node) {
|
|
121
|
+
// Test for custom error classes
|
|
122
|
+
if (node.argument?.type === 'NewExpression' &&
|
|
123
|
+
node.argument.callee?.name === 'Error') {
|
|
124
|
+
context.report({
|
|
125
|
+
node,
|
|
126
|
+
messageId: "customErrorRequired",
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const ruleTester = new RuleTester({
|
|
135
|
+
languageOptions: {
|
|
136
|
+
ecmaVersion: 2020,
|
|
137
|
+
sourceType: 'module',
|
|
138
|
+
},
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
console.log('Testing complexity rule...');
|
|
142
|
+
|
|
143
|
+
ruleTester.run('complexity', {
|
|
144
|
+
create: (context) => complexityRule.create(context),
|
|
145
|
+
meta: complexityRule.meta,
|
|
146
|
+
}, {
|
|
147
|
+
valid: [
|
|
148
|
+
// Valid cases
|
|
149
|
+
{
|
|
150
|
+
code: `
|
|
151
|
+
export default class ValidClass {
|
|
152
|
+
constructor() {
|
|
153
|
+
this.name = '';
|
|
154
|
+
this.value = 0;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
static create(data) {
|
|
158
|
+
const instance = new ValidClass();
|
|
159
|
+
instance.name = data.name;
|
|
160
|
+
return instance;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
processData(param1, param2) {
|
|
164
|
+
return param1 + param2;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
`,
|
|
168
|
+
filename: 'ValidClass.ts',
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
code: `
|
|
172
|
+
const VALID_CONSTANT = 42;
|
|
173
|
+
function processWithConstant() {
|
|
174
|
+
return VALID_CONSTANT;
|
|
175
|
+
}
|
|
176
|
+
`,
|
|
177
|
+
filename: 'Constants.ts',
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
code: `
|
|
181
|
+
import { UserDto } from './dto/UserDto';
|
|
182
|
+
|
|
183
|
+
function createUser() {
|
|
184
|
+
return new UserDto();
|
|
185
|
+
}
|
|
186
|
+
`,
|
|
187
|
+
filename: 'UserService.ts',
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
code: `
|
|
191
|
+
export class UserService {
|
|
192
|
+
constructor() {}
|
|
193
|
+
|
|
194
|
+
findById(id) {
|
|
195
|
+
if (!id) {
|
|
196
|
+
throw new CustomUserError('User ID required');
|
|
197
|
+
}
|
|
198
|
+
return { id, name: 'Test User' };
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
`,
|
|
202
|
+
filename: 'UserService.ts',
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
code: `
|
|
206
|
+
const config = {
|
|
207
|
+
apiUrl: 'https://api.example.com',
|
|
208
|
+
timeout: 5000,
|
|
209
|
+
retries: 3
|
|
210
|
+
};
|
|
211
|
+
`,
|
|
212
|
+
filename: 'config.ts',
|
|
213
|
+
},
|
|
214
|
+
],
|
|
215
|
+
|
|
216
|
+
invalid: [
|
|
217
|
+
// Invalid cases that should trigger rule violations
|
|
218
|
+
{
|
|
219
|
+
code: `
|
|
220
|
+
function badFunction() {
|
|
221
|
+
return 42; // Magic number
|
|
222
|
+
}
|
|
223
|
+
`,
|
|
224
|
+
filename: 'badFunction.ts',
|
|
225
|
+
errors: [{ messageId: 'magicValue' }],
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
code: `
|
|
229
|
+
const data = {
|
|
230
|
+
name: 'test',
|
|
231
|
+
value: 123 // Anonymous object + magic number
|
|
232
|
+
};
|
|
233
|
+
`,
|
|
234
|
+
filename: 'data.ts',
|
|
235
|
+
errors: [
|
|
236
|
+
{ messageId: 'anonymousObject' },
|
|
237
|
+
{ messageId: 'magicValue' }
|
|
238
|
+
],
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
code: `
|
|
242
|
+
// This is a comment
|
|
243
|
+
const value = 999; // Another comment with magic number
|
|
244
|
+
`,
|
|
245
|
+
filename: 'commented.ts',
|
|
246
|
+
errors: [
|
|
247
|
+
{ messageId: 'commentFound' },
|
|
248
|
+
{ messageId: 'commentFound' },
|
|
249
|
+
{ messageId: 'magicValue' }
|
|
250
|
+
],
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
code: `
|
|
254
|
+
export class FirstClass {}
|
|
255
|
+
export class SecondClass {}
|
|
256
|
+
`,
|
|
257
|
+
filename: 'MultipleClasses.ts',
|
|
258
|
+
errors: [{ messageId: 'multipleClasses' }],
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
code: `
|
|
262
|
+
function tooManyParams(a, b, c, d, e, f, g) {
|
|
263
|
+
return a + b + c + d + e + f + g;
|
|
264
|
+
}
|
|
265
|
+
`,
|
|
266
|
+
filename: 'complex.ts',
|
|
267
|
+
errors: [{ messageId: 'complexFunction' }],
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
code: `
|
|
271
|
+
function noParams() {
|
|
272
|
+
return 42;
|
|
273
|
+
}
|
|
274
|
+
`,
|
|
275
|
+
filename: 'noparams.ts',
|
|
276
|
+
errors: [
|
|
277
|
+
{ messageId: 'wrongArgumentCount' },
|
|
278
|
+
{ messageId: 'magicValue' }
|
|
279
|
+
],
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
code: `
|
|
283
|
+
function errorThrower() {
|
|
284
|
+
throw new Error('Generic error');
|
|
285
|
+
}
|
|
286
|
+
`,
|
|
287
|
+
filename: 'errors.ts',
|
|
288
|
+
errors: [{ messageId: 'customErrorRequired' }],
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
code: `
|
|
292
|
+
const germanText = "Hällö Wörld";
|
|
293
|
+
`,
|
|
294
|
+
filename: 'international.ts',
|
|
295
|
+
errors: [{ messageId: 'nonEnglishString' }],
|
|
296
|
+
},
|
|
297
|
+
],
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
console.log('✅ complexity tests completed successfully');
|