@futdevpro/dynamo-eslint 1.14.6 → 1.14.8
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/build/configs/base.js +12 -1
- package/build/configs/base.js.map +1 -1
- package/build/plugin/index.d.ts +8 -0
- package/build/plugin/index.d.ts.map +1 -1
- package/build/plugin/index.js +12 -0
- package/build/plugin/index.js.map +1 -1
- package/build/plugin/rules/explicit-types.js +2 -2
- package/build/plugin/rules/explicit-types.js.map +1 -1
- package/build/plugin/rules/import/import-order.d.ts.map +1 -1
- package/build/plugin/rules/import/import-order.js +41 -10
- package/build/plugin/rules/import/import-order.js.map +1 -1
- package/build/plugin/rules/import/import-order.spec.js +17 -1
- package/build/plugin/rules/import/import-order.spec.js.map +1 -1
- package/build/plugin/rules/prefer-enum-over-string-union.d.ts +4 -0
- package/build/plugin/rules/prefer-enum-over-string-union.d.ts.map +1 -0
- package/build/plugin/rules/prefer-enum-over-string-union.js +290 -0
- package/build/plugin/rules/prefer-enum-over-string-union.js.map +1 -0
- package/build/plugin/rules/prefer-enum-over-string-union.spec.d.ts +2 -0
- package/build/plugin/rules/prefer-enum-over-string-union.spec.d.ts.map +1 -0
- package/build/plugin/rules/prefer-enum-over-string-union.spec.js +505 -0
- package/build/plugin/rules/prefer-enum-over-string-union.spec.js.map +1 -0
- package/build/plugin/rules/prefer-interface-over-duplicate-types.d.ts +4 -0
- package/build/plugin/rules/prefer-interface-over-duplicate-types.d.ts.map +1 -0
- package/build/plugin/rules/prefer-interface-over-duplicate-types.js +231 -0
- package/build/plugin/rules/prefer-interface-over-duplicate-types.js.map +1 -0
- package/build/plugin/rules/prefer-interface-over-duplicate-types.spec.d.ts +2 -0
- package/build/plugin/rules/prefer-interface-over-duplicate-types.spec.d.ts.map +1 -0
- package/build/plugin/rules/prefer-interface-over-duplicate-types.spec.js +324 -0
- package/build/plugin/rules/prefer-interface-over-duplicate-types.spec.js.map +1 -0
- package/build/plugin/rules/require-jsdoc-description.d.ts +4 -0
- package/build/plugin/rules/require-jsdoc-description.d.ts.map +1 -0
- package/build/plugin/rules/require-jsdoc-description.js +379 -0
- package/build/plugin/rules/require-jsdoc-description.js.map +1 -0
- package/build/plugin/rules/require-jsdoc-description.spec.d.ts +2 -0
- package/build/plugin/rules/require-jsdoc-description.spec.d.ts.map +1 -0
- package/build/plugin/rules/require-jsdoc-description.spec.js +452 -0
- package/build/plugin/rules/require-jsdoc-description.spec.js.map +1 -0
- package/build/plugin/rules/require-test-description-prefix.d.ts +4 -0
- package/build/plugin/rules/require-test-description-prefix.d.ts.map +1 -0
- package/build/plugin/rules/require-test-description-prefix.js +135 -0
- package/build/plugin/rules/require-test-description-prefix.js.map +1 -0
- package/build/plugin/rules/require-test-description-prefix.spec.d.ts +2 -0
- package/build/plugin/rules/require-test-description-prefix.spec.d.ts.map +1 -0
- package/build/plugin/rules/require-test-description-prefix.spec.js +371 -0
- package/build/plugin/rules/require-test-description-prefix.spec.js.map +1 -0
- package/futdevpro-dynamo-eslint-1.14.8.tgz +0 -0
- package/package.json +1 -1
- package/src/configs/base.ts +12 -1
- package/src/plugin/index.ts +12 -0
- package/src/plugin/rules/explicit-types.ts +2 -2
- package/src/plugin/rules/import/import-order.spec.ts +17 -1
- package/src/plugin/rules/import/import-order.ts +47 -10
- package/src/plugin/rules/prefer-enum-over-string-union.spec.ts +583 -0
- package/src/plugin/rules/prefer-enum-over-string-union.ts +333 -0
- package/src/plugin/rules/prefer-interface-over-duplicate-types.spec.ts +374 -0
- package/src/plugin/rules/prefer-interface-over-duplicate-types.ts +276 -0
- package/src/plugin/rules/require-jsdoc-description.spec.ts +542 -0
- package/src/plugin/rules/require-jsdoc-description.ts +436 -0
- package/src/plugin/rules/require-test-description-prefix.spec.ts +459 -0
- package/src/plugin/rules/require-test-description-prefix.ts +153 -0
- package/futdevpro-dynamo-eslint-1.14.6.tgz +0 -0
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const require_test_description_prefix_1 = tslib_1.__importDefault(require("./require-test-description-prefix"));
|
|
5
|
+
describe('| require-test-description-prefix', () => {
|
|
6
|
+
it('| should be a valid ESLint rule', () => {
|
|
7
|
+
expect(require_test_description_prefix_1.default.meta.type).toBe('suggestion');
|
|
8
|
+
expect(require_test_description_prefix_1.default.meta.docs.description).toBe('Require "| " prefix in test descriptions');
|
|
9
|
+
expect(require_test_description_prefix_1.default.meta.fixable).toBe('code');
|
|
10
|
+
});
|
|
11
|
+
it('| should not report when describe has correct prefix', () => {
|
|
12
|
+
let reportCalled = false;
|
|
13
|
+
const mockContext = {
|
|
14
|
+
report: (options) => {
|
|
15
|
+
reportCalled = true;
|
|
16
|
+
},
|
|
17
|
+
options: [{ prefix: '| ' }],
|
|
18
|
+
};
|
|
19
|
+
const rule = require_test_description_prefix_1.default.create(mockContext);
|
|
20
|
+
const mockNode = {
|
|
21
|
+
type: 'CallExpression',
|
|
22
|
+
callee: { name: 'describe' },
|
|
23
|
+
arguments: [
|
|
24
|
+
{ type: 'Literal', value: '| my test suite' },
|
|
25
|
+
],
|
|
26
|
+
};
|
|
27
|
+
rule.CallExpression(mockNode);
|
|
28
|
+
expect(reportCalled).toBe(false);
|
|
29
|
+
});
|
|
30
|
+
it('| should not report when it has correct prefix', () => {
|
|
31
|
+
let reportCalled = false;
|
|
32
|
+
const mockContext = {
|
|
33
|
+
report: (options) => {
|
|
34
|
+
reportCalled = true;
|
|
35
|
+
},
|
|
36
|
+
options: [{ prefix: '| ' }],
|
|
37
|
+
};
|
|
38
|
+
const rule = require_test_description_prefix_1.default.create(mockContext);
|
|
39
|
+
const mockNode = {
|
|
40
|
+
type: 'CallExpression',
|
|
41
|
+
callee: { name: 'it' },
|
|
42
|
+
arguments: [
|
|
43
|
+
{ type: 'Literal', value: '| should do something' },
|
|
44
|
+
],
|
|
45
|
+
};
|
|
46
|
+
rule.CallExpression(mockNode);
|
|
47
|
+
expect(reportCalled).toBe(false);
|
|
48
|
+
});
|
|
49
|
+
it('| should not report when test has correct prefix', () => {
|
|
50
|
+
let reportCalled = false;
|
|
51
|
+
const mockContext = {
|
|
52
|
+
report: (options) => {
|
|
53
|
+
reportCalled = true;
|
|
54
|
+
},
|
|
55
|
+
options: [{ prefix: '| ' }],
|
|
56
|
+
};
|
|
57
|
+
const rule = require_test_description_prefix_1.default.create(mockContext);
|
|
58
|
+
const mockNode = {
|
|
59
|
+
type: 'CallExpression',
|
|
60
|
+
callee: { name: 'test' },
|
|
61
|
+
arguments: [
|
|
62
|
+
{ type: 'Literal', value: '| validates input' },
|
|
63
|
+
],
|
|
64
|
+
};
|
|
65
|
+
rule.CallExpression(mockNode);
|
|
66
|
+
expect(reportCalled).toBe(false);
|
|
67
|
+
});
|
|
68
|
+
it('| should report when describe is missing prefix', () => {
|
|
69
|
+
let reportCalled = false;
|
|
70
|
+
const mockContext = {
|
|
71
|
+
report: (options) => {
|
|
72
|
+
reportCalled = true;
|
|
73
|
+
expect(options.messageId).toBe('missingPrefix');
|
|
74
|
+
expect(options.data.prefix).toBe('| ');
|
|
75
|
+
expect(options.fix).toBeDefined();
|
|
76
|
+
},
|
|
77
|
+
options: [{ prefix: '| ' }],
|
|
78
|
+
};
|
|
79
|
+
const rule = require_test_description_prefix_1.default.create(mockContext);
|
|
80
|
+
const mockNode = {
|
|
81
|
+
type: 'CallExpression',
|
|
82
|
+
callee: { name: 'describe' },
|
|
83
|
+
arguments: [
|
|
84
|
+
{ type: 'Literal', value: 'my test suite' },
|
|
85
|
+
],
|
|
86
|
+
};
|
|
87
|
+
rule.CallExpression(mockNode);
|
|
88
|
+
expect(reportCalled).toBe(true);
|
|
89
|
+
});
|
|
90
|
+
it('| should report when it is missing prefix', () => {
|
|
91
|
+
let reportCalled = false;
|
|
92
|
+
const mockContext = {
|
|
93
|
+
report: (options) => {
|
|
94
|
+
reportCalled = true;
|
|
95
|
+
expect(options.messageId).toBe('missingPrefix');
|
|
96
|
+
expect(options.data.prefix).toBe('| ');
|
|
97
|
+
},
|
|
98
|
+
options: [{ prefix: '| ' }],
|
|
99
|
+
};
|
|
100
|
+
const rule = require_test_description_prefix_1.default.create(mockContext);
|
|
101
|
+
const mockNode = {
|
|
102
|
+
type: 'CallExpression',
|
|
103
|
+
callee: { name: 'it' },
|
|
104
|
+
arguments: [
|
|
105
|
+
{ type: 'Literal', value: 'should do something' },
|
|
106
|
+
],
|
|
107
|
+
};
|
|
108
|
+
rule.CallExpression(mockNode);
|
|
109
|
+
expect(reportCalled).toBe(true);
|
|
110
|
+
});
|
|
111
|
+
it('| should report when describe has wrong prefix', () => {
|
|
112
|
+
let reportCalled = false;
|
|
113
|
+
const mockContext = {
|
|
114
|
+
report: (options) => {
|
|
115
|
+
reportCalled = true;
|
|
116
|
+
expect(options.messageId).toBe('wrongPrefix');
|
|
117
|
+
expect(options.data.prefix).toBe('| ');
|
|
118
|
+
expect(options.data.found).toBe('|');
|
|
119
|
+
},
|
|
120
|
+
options: [{ prefix: '| ' }],
|
|
121
|
+
};
|
|
122
|
+
const rule = require_test_description_prefix_1.default.create(mockContext);
|
|
123
|
+
const mockNode = {
|
|
124
|
+
type: 'CallExpression',
|
|
125
|
+
callee: { name: 'describe' },
|
|
126
|
+
arguments: [
|
|
127
|
+
{ type: 'Literal', value: '|my test suite' },
|
|
128
|
+
],
|
|
129
|
+
};
|
|
130
|
+
rule.CallExpression(mockNode);
|
|
131
|
+
expect(reportCalled).toBe(true);
|
|
132
|
+
});
|
|
133
|
+
it('| should report when it has only pipe without space', () => {
|
|
134
|
+
let reportCalled = false;
|
|
135
|
+
const mockContext = {
|
|
136
|
+
report: (options) => {
|
|
137
|
+
reportCalled = true;
|
|
138
|
+
expect(options.messageId).toBe('wrongPrefix');
|
|
139
|
+
expect(options.data.found).toBe('|');
|
|
140
|
+
},
|
|
141
|
+
options: [{ prefix: '| ' }],
|
|
142
|
+
};
|
|
143
|
+
const rule = require_test_description_prefix_1.default.create(mockContext);
|
|
144
|
+
const mockNode = {
|
|
145
|
+
type: 'CallExpression',
|
|
146
|
+
callee: { name: 'it' },
|
|
147
|
+
arguments: [
|
|
148
|
+
{ type: 'Literal', value: '|should do something' },
|
|
149
|
+
],
|
|
150
|
+
};
|
|
151
|
+
rule.CallExpression(mockNode);
|
|
152
|
+
expect(reportCalled).toBe(true);
|
|
153
|
+
});
|
|
154
|
+
it('| should not report on non-test functions', () => {
|
|
155
|
+
let reportCalled = false;
|
|
156
|
+
const mockContext = {
|
|
157
|
+
report: (options) => {
|
|
158
|
+
reportCalled = true;
|
|
159
|
+
},
|
|
160
|
+
options: [{ prefix: '| ' }],
|
|
161
|
+
};
|
|
162
|
+
const rule = require_test_description_prefix_1.default.create(mockContext);
|
|
163
|
+
const mockNode = {
|
|
164
|
+
type: 'CallExpression',
|
|
165
|
+
callee: { name: 'console' },
|
|
166
|
+
arguments: [
|
|
167
|
+
{ type: 'Literal', value: 'log message' },
|
|
168
|
+
],
|
|
169
|
+
};
|
|
170
|
+
rule.CallExpression(mockNode);
|
|
171
|
+
expect(reportCalled).toBe(false);
|
|
172
|
+
});
|
|
173
|
+
it('| should not report when no arguments provided', () => {
|
|
174
|
+
let reportCalled = false;
|
|
175
|
+
const mockContext = {
|
|
176
|
+
report: (options) => {
|
|
177
|
+
reportCalled = true;
|
|
178
|
+
},
|
|
179
|
+
options: [{ prefix: '| ' }],
|
|
180
|
+
};
|
|
181
|
+
const rule = require_test_description_prefix_1.default.create(mockContext);
|
|
182
|
+
const mockNode = {
|
|
183
|
+
type: 'CallExpression',
|
|
184
|
+
callee: { name: 'describe' },
|
|
185
|
+
arguments: [],
|
|
186
|
+
};
|
|
187
|
+
rule.CallExpression(mockNode);
|
|
188
|
+
expect(reportCalled).toBe(false);
|
|
189
|
+
});
|
|
190
|
+
it('| should not report when first argument is not a string', () => {
|
|
191
|
+
let reportCalled = false;
|
|
192
|
+
const mockContext = {
|
|
193
|
+
report: (options) => {
|
|
194
|
+
reportCalled = true;
|
|
195
|
+
},
|
|
196
|
+
options: [{ prefix: '| ' }],
|
|
197
|
+
};
|
|
198
|
+
const rule = require_test_description_prefix_1.default.create(mockContext);
|
|
199
|
+
const mockNode = {
|
|
200
|
+
type: 'CallExpression',
|
|
201
|
+
callee: { name: 'describe' },
|
|
202
|
+
arguments: [
|
|
203
|
+
{ type: 'Identifier', name: 'myVariable' },
|
|
204
|
+
],
|
|
205
|
+
};
|
|
206
|
+
rule.CallExpression(mockNode);
|
|
207
|
+
expect(reportCalled).toBe(false);
|
|
208
|
+
});
|
|
209
|
+
it('| should handle beforeEach and afterEach', () => {
|
|
210
|
+
let reportCalled = false;
|
|
211
|
+
const mockContext = {
|
|
212
|
+
report: (options) => {
|
|
213
|
+
reportCalled = true;
|
|
214
|
+
expect(options.messageId).toBe('missingPrefix');
|
|
215
|
+
},
|
|
216
|
+
options: [{ prefix: '| ' }],
|
|
217
|
+
};
|
|
218
|
+
const rule = require_test_description_prefix_1.default.create(mockContext);
|
|
219
|
+
const mockNode = {
|
|
220
|
+
type: 'CallExpression',
|
|
221
|
+
callee: { name: 'beforeEach' },
|
|
222
|
+
arguments: [
|
|
223
|
+
{ type: 'Literal', value: 'setup test data' },
|
|
224
|
+
],
|
|
225
|
+
};
|
|
226
|
+
rule.CallExpression(mockNode);
|
|
227
|
+
expect(reportCalled).toBe(true);
|
|
228
|
+
});
|
|
229
|
+
it('| should handle beforeAll and afterAll', () => {
|
|
230
|
+
let reportCalled = false;
|
|
231
|
+
const mockContext = {
|
|
232
|
+
report: (options) => {
|
|
233
|
+
reportCalled = true;
|
|
234
|
+
expect(options.messageId).toBe('missingPrefix');
|
|
235
|
+
},
|
|
236
|
+
options: [{ prefix: '| ' }],
|
|
237
|
+
};
|
|
238
|
+
const rule = require_test_description_prefix_1.default.create(mockContext);
|
|
239
|
+
const mockNode = {
|
|
240
|
+
type: 'CallExpression',
|
|
241
|
+
callee: { name: 'beforeAll' },
|
|
242
|
+
arguments: [
|
|
243
|
+
{ type: 'Literal', value: 'setup suite' },
|
|
244
|
+
],
|
|
245
|
+
};
|
|
246
|
+
rule.CallExpression(mockNode);
|
|
247
|
+
expect(reportCalled).toBe(true);
|
|
248
|
+
});
|
|
249
|
+
it('| should handle custom prefix configuration', () => {
|
|
250
|
+
let reportCalled = false;
|
|
251
|
+
const mockContext = {
|
|
252
|
+
report: (options) => {
|
|
253
|
+
reportCalled = true;
|
|
254
|
+
expect(options.data.prefix).toBe('>>> ');
|
|
255
|
+
},
|
|
256
|
+
options: [{ prefix: '>>> ' }],
|
|
257
|
+
};
|
|
258
|
+
const rule = require_test_description_prefix_1.default.create(mockContext);
|
|
259
|
+
const mockNode = {
|
|
260
|
+
type: 'CallExpression',
|
|
261
|
+
callee: { name: 'describe' },
|
|
262
|
+
arguments: [
|
|
263
|
+
{ type: 'Literal', value: 'my test suite' },
|
|
264
|
+
],
|
|
265
|
+
};
|
|
266
|
+
rule.CallExpression(mockNode);
|
|
267
|
+
expect(reportCalled).toBe(true);
|
|
268
|
+
});
|
|
269
|
+
it('| should handle custom test functions configuration', () => {
|
|
270
|
+
let reportCalled = false;
|
|
271
|
+
const mockContext = {
|
|
272
|
+
report: (options) => {
|
|
273
|
+
reportCalled = true;
|
|
274
|
+
},
|
|
275
|
+
options: [{ testFunctions: ['myTest'] }],
|
|
276
|
+
};
|
|
277
|
+
const rule = require_test_description_prefix_1.default.create(mockContext);
|
|
278
|
+
const mockNode = {
|
|
279
|
+
type: 'CallExpression',
|
|
280
|
+
callee: { name: 'myTest' },
|
|
281
|
+
arguments: [
|
|
282
|
+
{ type: 'Literal', value: 'my test description' },
|
|
283
|
+
],
|
|
284
|
+
};
|
|
285
|
+
rule.CallExpression(mockNode);
|
|
286
|
+
expect(reportCalled).toBe(true);
|
|
287
|
+
});
|
|
288
|
+
it('| should provide auto-fix functionality', () => {
|
|
289
|
+
const mockContext = {
|
|
290
|
+
report: (options) => {
|
|
291
|
+
expect(options.fix).toBeDefined();
|
|
292
|
+
expect(typeof options.fix).toBe('function');
|
|
293
|
+
// Test the fix function
|
|
294
|
+
const fixResult = options.fix({
|
|
295
|
+
replaceText: (node, text) => {
|
|
296
|
+
expect(text).toBe('\'| my test suite\'');
|
|
297
|
+
return [];
|
|
298
|
+
},
|
|
299
|
+
});
|
|
300
|
+
expect(Array.isArray(fixResult)).toBe(true);
|
|
301
|
+
},
|
|
302
|
+
options: [{ prefix: '| ' }],
|
|
303
|
+
};
|
|
304
|
+
const rule = require_test_description_prefix_1.default.create(mockContext);
|
|
305
|
+
const mockNode = {
|
|
306
|
+
type: 'CallExpression',
|
|
307
|
+
callee: { name: 'describe' },
|
|
308
|
+
arguments: [
|
|
309
|
+
{ type: 'Literal', value: 'my test suite' },
|
|
310
|
+
],
|
|
311
|
+
};
|
|
312
|
+
rule.CallExpression(mockNode);
|
|
313
|
+
});
|
|
314
|
+
it('| should handle empty string descriptions', () => {
|
|
315
|
+
let reportCalled = false;
|
|
316
|
+
const mockContext = {
|
|
317
|
+
report: (options) => {
|
|
318
|
+
reportCalled = true;
|
|
319
|
+
expect(options.messageId).toBe('missingPrefix');
|
|
320
|
+
},
|
|
321
|
+
options: [{ prefix: '| ' }],
|
|
322
|
+
};
|
|
323
|
+
const rule = require_test_description_prefix_1.default.create(mockContext);
|
|
324
|
+
const mockNode = {
|
|
325
|
+
type: 'CallExpression',
|
|
326
|
+
callee: { name: 'describe' },
|
|
327
|
+
arguments: [
|
|
328
|
+
{ type: 'Literal', value: '' },
|
|
329
|
+
],
|
|
330
|
+
};
|
|
331
|
+
rule.CallExpression(mockNode);
|
|
332
|
+
expect(reportCalled).toBe(true);
|
|
333
|
+
});
|
|
334
|
+
it('| should handle errors gracefully', () => {
|
|
335
|
+
const mockContext = {
|
|
336
|
+
report: (options) => {
|
|
337
|
+
// Should not throw
|
|
338
|
+
},
|
|
339
|
+
options: [{ prefix: '| ' }],
|
|
340
|
+
};
|
|
341
|
+
const rule = require_test_description_prefix_1.default.create(mockContext);
|
|
342
|
+
// Test with malformed nodes
|
|
343
|
+
const malformedNode = {
|
|
344
|
+
type: 'CallExpression',
|
|
345
|
+
// Missing required properties
|
|
346
|
+
};
|
|
347
|
+
expect(() => {
|
|
348
|
+
rule.CallExpression(malformedNode);
|
|
349
|
+
}).not.toThrow();
|
|
350
|
+
});
|
|
351
|
+
it('| should handle missing callee gracefully', () => {
|
|
352
|
+
let reportCalled = false;
|
|
353
|
+
const mockContext = {
|
|
354
|
+
report: (options) => {
|
|
355
|
+
reportCalled = true;
|
|
356
|
+
},
|
|
357
|
+
options: [{ prefix: '| ' }],
|
|
358
|
+
};
|
|
359
|
+
const rule = require_test_description_prefix_1.default.create(mockContext);
|
|
360
|
+
const mockNode = {
|
|
361
|
+
type: 'CallExpression',
|
|
362
|
+
// Missing callee
|
|
363
|
+
arguments: [
|
|
364
|
+
{ type: 'Literal', value: 'my test suite' },
|
|
365
|
+
],
|
|
366
|
+
};
|
|
367
|
+
rule.CallExpression(mockNode);
|
|
368
|
+
expect(reportCalled).toBe(false);
|
|
369
|
+
});
|
|
370
|
+
});
|
|
371
|
+
//# sourceMappingURL=require-test-description-prefix.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"require-test-description-prefix.spec.js","sourceRoot":"","sources":["../../../src/plugin/rules/require-test-description-prefix.spec.ts"],"names":[],"mappings":";;;AAAA,gHAAsE;AAEtE,QAAQ,CAAC,mCAAmC,EAAE,GAAG,EAAE;IACjD,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QACzC,MAAM,CAAC,yCAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC3D,MAAM,CAAC,yCAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;QACrG,MAAM,CAAC,yCAAqB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;QAC9D,IAAI,YAAY,GAAG,KAAK,CAAC;QACzB,MAAM,WAAW,GAAG;YAClB,MAAM,EAAE,CAAC,OAAY,EAAE,EAAE;gBACvB,YAAY,GAAG,IAAI,CAAC;YACtB,CAAC;YACD,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;SACrB,CAAC;QAET,MAAM,IAAI,GAAG,yCAAqB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAEvD,MAAM,QAAQ,GAAG;YACf,IAAI,EAAE,gBAAgB;YACtB,MAAM,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;YAC5B,SAAS,EAAE;gBACT,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,iBAAiB,EAAE;aAC9C;SACK,CAAC;QAET,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAE9B,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,IAAI,YAAY,GAAG,KAAK,CAAC;QACzB,MAAM,WAAW,GAAG;YAClB,MAAM,EAAE,CAAC,OAAY,EAAE,EAAE;gBACvB,YAAY,GAAG,IAAI,CAAC;YACtB,CAAC;YACD,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;SACrB,CAAC;QAET,MAAM,IAAI,GAAG,yCAAqB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAEvD,MAAM,QAAQ,GAAG;YACf,IAAI,EAAE,gBAAgB;YACtB,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE;YACtB,SAAS,EAAE;gBACT,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,uBAAuB,EAAE;aACpD;SACK,CAAC;QAET,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAE9B,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,IAAI,YAAY,GAAG,KAAK,CAAC;QACzB,MAAM,WAAW,GAAG;YAClB,MAAM,EAAE,CAAC,OAAY,EAAE,EAAE;gBACvB,YAAY,GAAG,IAAI,CAAC;YACtB,CAAC;YACD,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;SACrB,CAAC;QAET,MAAM,IAAI,GAAG,yCAAqB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAEvD,MAAM,QAAQ,GAAG;YACf,IAAI,EAAE,gBAAgB;YACtB,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;YACxB,SAAS,EAAE;gBACT,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,mBAAmB,EAAE;aAChD;SACK,CAAC;QAET,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAE9B,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,IAAI,YAAY,GAAG,KAAK,CAAC;QACzB,MAAM,WAAW,GAAG;YAClB,MAAM,EAAE,CAAC,OAAY,EAAE,EAAE;gBACvB,YAAY,GAAG,IAAI,CAAC;gBACpB,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;gBAChD,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACvC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;YACpC,CAAC;YACD,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;SACrB,CAAC;QAET,MAAM,IAAI,GAAG,yCAAqB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAEvD,MAAM,QAAQ,GAAG;YACf,IAAI,EAAE,gBAAgB;YACtB,MAAM,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;YAC5B,SAAS,EAAE;gBACT,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,eAAe,EAAE;aAC5C;SACK,CAAC;QAET,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAE9B,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,IAAI,YAAY,GAAG,KAAK,CAAC;QACzB,MAAM,WAAW,GAAG;YAClB,MAAM,EAAE,CAAC,OAAY,EAAE,EAAE;gBACvB,YAAY,GAAG,IAAI,CAAC;gBACpB,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;gBAChD,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACzC,CAAC;YACD,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;SACrB,CAAC;QAET,MAAM,IAAI,GAAG,yCAAqB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAEvD,MAAM,QAAQ,GAAG;YACf,IAAI,EAAE,gBAAgB;YACtB,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE;YACtB,SAAS,EAAE;gBACT,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,qBAAqB,EAAE;aAClD;SACK,CAAC;QAET,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAE9B,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,IAAI,YAAY,GAAG,KAAK,CAAC;QACzB,MAAM,WAAW,GAAG;YAClB,MAAM,EAAE,CAAC,OAAY,EAAE,EAAE;gBACvB,YAAY,GAAG,IAAI,CAAC;gBACpB,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;gBAC9C,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACvC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACvC,CAAC;YACD,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;SACrB,CAAC;QAET,MAAM,IAAI,GAAG,yCAAqB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAEvD,MAAM,QAAQ,GAAG;YACf,IAAI,EAAE,gBAAgB;YACtB,MAAM,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;YAC5B,SAAS,EAAE;gBACT,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,gBAAgB,EAAE;aAC7C;SACK,CAAC;QAET,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAE9B,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,IAAI,YAAY,GAAG,KAAK,CAAC;QACzB,MAAM,WAAW,GAAG;YAClB,MAAM,EAAE,CAAC,OAAY,EAAE,EAAE;gBACvB,YAAY,GAAG,IAAI,CAAC;gBACpB,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;gBAC9C,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACvC,CAAC;YACD,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;SACrB,CAAC;QAET,MAAM,IAAI,GAAG,yCAAqB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAEvD,MAAM,QAAQ,GAAG;YACf,IAAI,EAAE,gBAAgB;YACtB,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE;YACtB,SAAS,EAAE;gBACT,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,sBAAsB,EAAE;aACnD;SACK,CAAC;QAET,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAE9B,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,IAAI,YAAY,GAAG,KAAK,CAAC;QACzB,MAAM,WAAW,GAAG;YAClB,MAAM,EAAE,CAAC,OAAY,EAAE,EAAE;gBACvB,YAAY,GAAG,IAAI,CAAC;YACtB,CAAC;YACD,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;SACrB,CAAC;QAET,MAAM,IAAI,GAAG,yCAAqB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAEvD,MAAM,QAAQ,GAAG;YACf,IAAI,EAAE,gBAAgB;YACtB,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;YAC3B,SAAS,EAAE;gBACT,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,aAAa,EAAE;aAC1C;SACK,CAAC;QAET,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAE9B,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,IAAI,YAAY,GAAG,KAAK,CAAC;QACzB,MAAM,WAAW,GAAG;YAClB,MAAM,EAAE,CAAC,OAAY,EAAE,EAAE;gBACvB,YAAY,GAAG,IAAI,CAAC;YACtB,CAAC;YACD,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;SACrB,CAAC;QAET,MAAM,IAAI,GAAG,yCAAqB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAEvD,MAAM,QAAQ,GAAG;YACf,IAAI,EAAE,gBAAgB;YACtB,MAAM,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;YAC5B,SAAS,EAAE,EAAE;SACP,CAAC;QAET,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAE9B,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACjE,IAAI,YAAY,GAAG,KAAK,CAAC;QACzB,MAAM,WAAW,GAAG;YAClB,MAAM,EAAE,CAAC,OAAY,EAAE,EAAE;gBACvB,YAAY,GAAG,IAAI,CAAC;YACtB,CAAC;YACD,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;SACrB,CAAC;QAET,MAAM,IAAI,GAAG,yCAAqB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAEvD,MAAM,QAAQ,GAAG;YACf,IAAI,EAAE,gBAAgB;YACtB,MAAM,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;YAC5B,SAAS,EAAE;gBACT,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,EAAE;aAC3C;SACK,CAAC;QAET,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAE9B,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,IAAI,YAAY,GAAG,KAAK,CAAC;QACzB,MAAM,WAAW,GAAG;YAClB,MAAM,EAAE,CAAC,OAAY,EAAE,EAAE;gBACvB,YAAY,GAAG,IAAI,CAAC;gBACpB,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YAClD,CAAC;YACD,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;SACrB,CAAC;QAET,MAAM,IAAI,GAAG,yCAAqB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAEvD,MAAM,QAAQ,GAAG;YACf,IAAI,EAAE,gBAAgB;YACtB,MAAM,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE;YAC9B,SAAS,EAAE;gBACT,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,iBAAiB,EAAE;aAC9C;SACK,CAAC;QAET,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAE9B,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,IAAI,YAAY,GAAG,KAAK,CAAC;QACzB,MAAM,WAAW,GAAG;YAClB,MAAM,EAAE,CAAC,OAAY,EAAE,EAAE;gBACvB,YAAY,GAAG,IAAI,CAAC;gBACpB,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YAClD,CAAC;YACD,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;SACrB,CAAC;QAET,MAAM,IAAI,GAAG,yCAAqB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAEvD,MAAM,QAAQ,GAAG;YACf,IAAI,EAAE,gBAAgB;YACtB,MAAM,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE;YAC7B,SAAS,EAAE;gBACT,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,aAAa,EAAE;aAC1C;SACK,CAAC;QAET,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAE9B,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,IAAI,YAAY,GAAG,KAAK,CAAC;QACzB,MAAM,WAAW,GAAG;YAClB,MAAM,EAAE,CAAC,OAAY,EAAE,EAAE;gBACvB,YAAY,GAAG,IAAI,CAAC;gBACpB,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC3C,CAAC;YACD,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;SACvB,CAAC;QAET,MAAM,IAAI,GAAG,yCAAqB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAEvD,MAAM,QAAQ,GAAG;YACf,IAAI,EAAE,gBAAgB;YACtB,MAAM,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;YAC5B,SAAS,EAAE;gBACT,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,eAAe,EAAE;aAC5C;SACK,CAAC;QAET,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAE9B,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,IAAI,YAAY,GAAG,KAAK,CAAC;QACzB,MAAM,WAAW,GAAG;YAClB,MAAM,EAAE,CAAC,OAAY,EAAE,EAAE;gBACvB,YAAY,GAAG,IAAI,CAAC;YACtB,CAAC;YACD,OAAO,EAAE,CAAC,EAAE,aAAa,EAAE,CAAE,QAAQ,CAAE,EAAE,CAAC;SACpC,CAAC;QAET,MAAM,IAAI,GAAG,yCAAqB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAEvD,MAAM,QAAQ,GAAG;YACf,IAAI,EAAE,gBAAgB;YACtB,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YAC1B,SAAS,EAAE;gBACT,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,qBAAqB,EAAE;aAClD;SACK,CAAC;QAET,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAE9B,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,WAAW,GAAG;YAClB,MAAM,EAAE,CAAC,OAAY,EAAE,EAAE;gBACvB,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;gBAClC,MAAM,CAAC,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBAE5C,wBAAwB;gBACxB,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC;oBAC5B,WAAW,EAAE,CAAC,IAAS,EAAE,IAAY,EAAE,EAAE;wBACvC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;wBAEzC,OAAO,EAAE,CAAC;oBACZ,CAAC;iBACF,CAAC,CAAC;gBAEH,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC9C,CAAC;YACD,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;SACrB,CAAC;QAET,MAAM,IAAI,GAAG,yCAAqB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAEvD,MAAM,QAAQ,GAAG;YACf,IAAI,EAAE,gBAAgB;YACtB,MAAM,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;YAC5B,SAAS,EAAE;gBACT,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,eAAe,EAAE;aAC5C;SACK,CAAC;QAET,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,IAAI,YAAY,GAAG,KAAK,CAAC;QACzB,MAAM,WAAW,GAAG;YAClB,MAAM,EAAE,CAAC,OAAY,EAAE,EAAE;gBACvB,YAAY,GAAG,IAAI,CAAC;gBACpB,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YAClD,CAAC;YACD,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;SACrB,CAAC;QAET,MAAM,IAAI,GAAG,yCAAqB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAEvD,MAAM,QAAQ,GAAG;YACf,IAAI,EAAE,gBAAgB;YACtB,MAAM,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;YAC5B,SAAS,EAAE;gBACT,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,EAAE;aAC/B;SACK,CAAC;QAET,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAE9B,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,WAAW,GAAG;YAClB,MAAM,EAAE,CAAC,OAAY,EAAE,EAAE;gBACvB,mBAAmB;YACrB,CAAC;YACD,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;SACrB,CAAC;QAET,MAAM,IAAI,GAAG,yCAAqB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAEvD,4BAA4B;QAC5B,MAAM,aAAa,GAAG;YACpB,IAAI,EAAE,gBAAgB;YACtB,8BAA8B;SACxB,CAAC;QAET,MAAM,CAAC,GAAG,EAAE;YACV,IAAI,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;IACnB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,IAAI,YAAY,GAAG,KAAK,CAAC;QACzB,MAAM,WAAW,GAAG;YAClB,MAAM,EAAE,CAAC,OAAY,EAAE,EAAE;gBACvB,YAAY,GAAG,IAAI,CAAC;YACtB,CAAC;YACD,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;SACrB,CAAC;QAET,MAAM,IAAI,GAAG,yCAAqB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAEvD,MAAM,QAAQ,GAAG;YACf,IAAI,EAAE,gBAAgB;YACtB,iBAAiB;YACjB,SAAS,EAAE;gBACT,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,eAAe,EAAE;aAC5C;SACK,CAAC;QAET,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAE9B,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
Binary file
|
package/package.json
CHANGED
package/src/configs/base.ts
CHANGED
|
@@ -69,6 +69,7 @@ module.exports = [
|
|
|
69
69
|
},
|
|
70
70
|
],
|
|
71
71
|
'brace-style': [ 'warn', '1tbs', { allowSingleLine: false }],
|
|
72
|
+
'curly': [ 'warn', 'all' ],
|
|
72
73
|
'object-curly-spacing': [ 'warn', 'always' ],
|
|
73
74
|
'array-bracket-spacing': [ 'warn', 'always', { objectsInArrays: false, arraysInArrays: false }],
|
|
74
75
|
'padding-line-between-statements': [
|
|
@@ -93,7 +94,13 @@ module.exports = [
|
|
|
93
94
|
'@typescript-eslint/no-unused-vars': 'warn',
|
|
94
95
|
'@typescript-eslint/explicit-function-return-type': [ 'warn', { allowTypedFunctionExpressions: false }],
|
|
95
96
|
'@typescript-eslint/no-explicit-any': 'warn',
|
|
96
|
-
'@typescript-eslint/typedef':
|
|
97
|
+
'@typescript-eslint/typedef': [
|
|
98
|
+
'warn',
|
|
99
|
+
{
|
|
100
|
+
parameter: true, // Enforce parameter type annotations
|
|
101
|
+
},
|
|
102
|
+
],
|
|
103
|
+
'@typescript-eslint/no-unnecessary-type-assertion': 'warn',
|
|
97
104
|
|
|
98
105
|
// Dynamo custom rules
|
|
99
106
|
'@futdevpro/dynamo/explicit-types': 'warn',
|
|
@@ -101,6 +108,10 @@ module.exports = [
|
|
|
101
108
|
'@futdevpro/dynamo/naming-patterns': 'warn',
|
|
102
109
|
'@futdevpro/dynamo/no-import-type': 'warn',
|
|
103
110
|
'@futdevpro/dynamo/no-js-import': 'warn',
|
|
111
|
+
'@futdevpro/dynamo/prefer-interface-over-duplicate-types': [ 'warn', { threshold: 3 }],
|
|
112
|
+
'@futdevpro/dynamo/require-jsdoc-description': [ 'warn', { scope: 'public' }],
|
|
113
|
+
'@futdevpro/dynamo/prefer-enum-over-string-union': [ 'warn', { minValues: 3 }],
|
|
114
|
+
'@futdevpro/dynamo/require-test-description-prefix': [ 'warn', { prefix: '| ' }],
|
|
104
115
|
},
|
|
105
116
|
},
|
|
106
117
|
];
|
package/src/plugin/index.ts
CHANGED
|
@@ -3,6 +3,10 @@ import importOrderRule from './rules/import/import-order';
|
|
|
3
3
|
import namingPatternsRule from './rules/naming-patterns';
|
|
4
4
|
import noImportTypeRule from './rules/import/no-import-type';
|
|
5
5
|
import noJsExtensionRule from './rules/import/no-js-import';
|
|
6
|
+
import preferInterfaceRule from './rules/prefer-interface-over-duplicate-types';
|
|
7
|
+
import requireJSDocRule from './rules/require-jsdoc-description';
|
|
8
|
+
import preferEnumRule from './rules/prefer-enum-over-string-union';
|
|
9
|
+
import requireTestPrefixRule from './rules/require-test-description-prefix';
|
|
6
10
|
|
|
7
11
|
export = {
|
|
8
12
|
rules: {
|
|
@@ -10,6 +14,10 @@ export = {
|
|
|
10
14
|
'import-order': importOrderRule,
|
|
11
15
|
'no-import-type': noImportTypeRule,
|
|
12
16
|
'no-js-import': noJsExtensionRule,
|
|
17
|
+
'prefer-interface-over-duplicate-types': preferInterfaceRule,
|
|
18
|
+
'require-jsdoc-description': requireJSDocRule,
|
|
19
|
+
'prefer-enum-over-string-union': preferEnumRule,
|
|
20
|
+
'require-test-description-prefix': requireTestPrefixRule,
|
|
13
21
|
|
|
14
22
|
'naming-patterns': namingPatternsRule,
|
|
15
23
|
},
|
|
@@ -20,6 +28,10 @@ export = {
|
|
|
20
28
|
'@futdevpro/dynamo/import-order': 'warn',
|
|
21
29
|
'@futdevpro/dynamo/no-import-type': 'warn',
|
|
22
30
|
'@futdevpro/dynamo/no-js-import': 'warn',
|
|
31
|
+
'@futdevpro/dynamo/prefer-interface-over-duplicate-types': 'warn',
|
|
32
|
+
'@futdevpro/dynamo/require-jsdoc-description': 'warn',
|
|
33
|
+
'@futdevpro/dynamo/prefer-enum-over-string-union': 'warn',
|
|
34
|
+
'@futdevpro/dynamo/require-test-description-prefix': 'warn',
|
|
23
35
|
|
|
24
36
|
'@futdevpro/dynamo/naming-patterns': 'warn',
|
|
25
37
|
},
|
|
@@ -25,7 +25,7 @@ const rule: Rule.RuleModule = {
|
|
|
25
25
|
// Check return type
|
|
26
26
|
if (!node.returnType) {
|
|
27
27
|
context.report({
|
|
28
|
-
node,
|
|
28
|
+
node: node.id || node, // Report on function name if available
|
|
29
29
|
messageId: 'missingReturnType',
|
|
30
30
|
data: { name: node.id?.name || 'anonymous' },
|
|
31
31
|
});
|
|
@@ -58,7 +58,7 @@ const rule: Rule.RuleModule = {
|
|
|
58
58
|
// Check return type
|
|
59
59
|
if (!node.returnType) {
|
|
60
60
|
context.report({
|
|
61
|
-
node,
|
|
61
|
+
node: node.params.length > 0 ? node.params[0] : node, // Report on first param or node
|
|
62
62
|
messageId: 'missingArrowReturnType',
|
|
63
63
|
});
|
|
64
64
|
}
|
|
@@ -159,6 +159,7 @@ describe('| import-order', () => {
|
|
|
159
159
|
|
|
160
160
|
it('| should detect missing empty line between groups', () => {
|
|
161
161
|
let reportCount = 0;
|
|
162
|
+
let hasFix = false;
|
|
162
163
|
const mockContext = {
|
|
163
164
|
sourceCode: {
|
|
164
165
|
ast: {},
|
|
@@ -166,12 +167,24 @@ describe('| import-order', () => {
|
|
|
166
167
|
'import { Component } from \'@angular/core\';',
|
|
167
168
|
'import { DyFM_Error } from \'@futdevpro/fsm-dynamo\';',
|
|
168
169
|
],
|
|
170
|
+
getText: (node: any) => {
|
|
171
|
+
if (node.source?.value === '@angular/core') {
|
|
172
|
+
return 'import { Component } from \'@angular/core\';';
|
|
173
|
+
}
|
|
174
|
+
if (node.source?.value === '@futdevpro/fsm-dynamo') {
|
|
175
|
+
return 'import { DyFM_Error } from \'@futdevpro/fsm-dynamo\';';
|
|
176
|
+
}
|
|
177
|
+
return '';
|
|
178
|
+
},
|
|
169
179
|
},
|
|
170
180
|
filename: 'test.ts',
|
|
171
181
|
report: (options: any) => {
|
|
172
|
-
if (options.messageId === '
|
|
182
|
+
if (options.messageId === 'misordered') {
|
|
173
183
|
reportCount++;
|
|
174
184
|
}
|
|
185
|
+
if (options.fix) {
|
|
186
|
+
hasFix = true;
|
|
187
|
+
}
|
|
175
188
|
},
|
|
176
189
|
} as any;
|
|
177
190
|
|
|
@@ -184,12 +197,14 @@ describe('| import-order', () => {
|
|
|
184
197
|
source: { value: '@angular/core' },
|
|
185
198
|
importKind: 'value',
|
|
186
199
|
loc: { start: { line: 1 }, end: { line: 1 } },
|
|
200
|
+
range: [0, 40],
|
|
187
201
|
},
|
|
188
202
|
{
|
|
189
203
|
type: 'ImportDeclaration',
|
|
190
204
|
source: { value: '@futdevpro/fsm-dynamo' },
|
|
191
205
|
importKind: 'value',
|
|
192
206
|
loc: { start: { line: 2 }, end: { line: 2 } },
|
|
207
|
+
range: [41, 85],
|
|
193
208
|
},
|
|
194
209
|
],
|
|
195
210
|
} as any;
|
|
@@ -199,5 +214,6 @@ describe('| import-order', () => {
|
|
|
199
214
|
rule.Program(mockNode);
|
|
200
215
|
|
|
201
216
|
expect(reportCount).toBeGreaterThan(0);
|
|
217
|
+
expect(hasFix).toBe(true);
|
|
202
218
|
});
|
|
203
219
|
});
|
|
@@ -100,26 +100,24 @@ const rule: Rule.RuleModule = {
|
|
|
100
100
|
// Remove empty groups
|
|
101
101
|
const nonEmptyGroups = groups.filter(group => group.imports.length > 0);
|
|
102
102
|
|
|
103
|
-
// Check if imports are in correct order
|
|
103
|
+
// Check if imports are in correct order and detect violations
|
|
104
|
+
let needsReordering = false;
|
|
104
105
|
let currentGroupIndex = 0;
|
|
105
106
|
|
|
106
107
|
for (let i = 0; i < importNodes.length; i++) {
|
|
107
108
|
const importNode = importNodes[i];
|
|
108
109
|
const expectedGroupType = getImportGroup(importNode);
|
|
109
|
-
const expectedGroup = nonEmptyGroups.find(g => g.type === expectedGroupType);
|
|
110
110
|
const expectedGroupIndex = nonEmptyGroups.findIndex(g => g.type === expectedGroupType);
|
|
111
111
|
|
|
112
112
|
if (expectedGroupIndex < currentGroupIndex) {
|
|
113
|
-
|
|
114
|
-
node: importNode,
|
|
115
|
-
messageId: 'misordered',
|
|
116
|
-
});
|
|
113
|
+
needsReordering = true;
|
|
117
114
|
}
|
|
118
115
|
|
|
119
116
|
currentGroupIndex = expectedGroupIndex;
|
|
120
117
|
}
|
|
121
118
|
|
|
122
119
|
// Check empty lines between groups
|
|
120
|
+
let needsEmptyLineFix = false;
|
|
123
121
|
for (let i = 0; i < nonEmptyGroups.length - 1; i++) {
|
|
124
122
|
const currentGroup = nonEmptyGroups[i];
|
|
125
123
|
const nextGroup = nonEmptyGroups[i + 1];
|
|
@@ -131,12 +129,51 @@ const rule: Rule.RuleModule = {
|
|
|
131
129
|
const firstImportLine = firstImportOfNextGroup.loc?.start.line || 0;
|
|
132
130
|
|
|
133
131
|
if (firstImportLine - lastImportLine < 2) {
|
|
134
|
-
|
|
135
|
-
node: firstImportOfNextGroup,
|
|
136
|
-
messageId: 'missingEmptyLine',
|
|
137
|
-
});
|
|
132
|
+
needsEmptyLineFix = true;
|
|
138
133
|
}
|
|
139
134
|
}
|
|
135
|
+
|
|
136
|
+
// If any violations are detected, provide a comprehensive fix
|
|
137
|
+
if (needsReordering || needsEmptyLineFix) {
|
|
138
|
+
context.report({
|
|
139
|
+
node: importNodes[0],
|
|
140
|
+
messageId: 'misordered',
|
|
141
|
+
fix(fixer) {
|
|
142
|
+
// Sort imports within each group alphabetically
|
|
143
|
+
nonEmptyGroups.forEach(group => {
|
|
144
|
+
group.imports.sort((a, b) => {
|
|
145
|
+
const aSource = a.source.value as string;
|
|
146
|
+
const bSource = b.source.value as string;
|
|
147
|
+
return aSource.localeCompare(bSource);
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
// Build the corrected import section
|
|
152
|
+
const correctedImports: string[] = [];
|
|
153
|
+
|
|
154
|
+
nonEmptyGroups.forEach((group, groupIndex) => {
|
|
155
|
+
group.imports.forEach(importNode => {
|
|
156
|
+
const importText = sourceCode.getText(importNode);
|
|
157
|
+
correctedImports.push(importText);
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
// Add empty line between groups (except after the last group)
|
|
161
|
+
if (groupIndex < nonEmptyGroups.length - 1) {
|
|
162
|
+
correctedImports.push('');
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
// Calculate the range to replace (from first import to last import)
|
|
167
|
+
const firstImport = importNodes[0];
|
|
168
|
+
const lastImport = importNodes[importNodes.length - 1];
|
|
169
|
+
const startRange = firstImport.range![0];
|
|
170
|
+
const endRange = lastImport.range![1];
|
|
171
|
+
|
|
172
|
+
// Replace the entire import section
|
|
173
|
+
return fixer.replaceTextRange([startRange, endRange], correctedImports.join('\n'));
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
}
|
|
140
177
|
}
|
|
141
178
|
|
|
142
179
|
return {
|