eslint-cdk-plugin 2.2.0 → 3.0.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/index.cjs +149 -178
- package/dist/index.d.ts +39 -39
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +149 -178
- package/package.json +12 -11
- package/src/index.ts +29 -28
- package/src/rules/construct-constructor-property.ts +4 -4
- package/src/rules/{no-class-in-interface.ts → no-construct-in-interface.ts} +8 -14
- package/src/rules/no-construct-in-public-property-of-construct.ts +145 -0
- package/src/rules/no-construct-stack-suffix.ts +6 -6
- package/src/rules/no-import-private.ts +2 -2
- package/src/rules/no-mutable-property-of-props-interface.ts +60 -0
- package/src/rules/no-mutable-public-property-of-construct.ts +76 -0
- package/src/rules/no-parent-name-construct-id-match.ts +6 -28
- package/src/rules/no-variable-construct-id.ts +4 -4
- package/src/rules/pascal-case-construct-id.ts +4 -4
- package/src/rules/require-passing-this.ts +6 -6
- package/src/rules/no-mutable-props-interface.ts +0 -58
- package/src/rules/no-mutable-public-fields.ts +0 -75
- package/src/rules/no-public-class-fields.ts +0 -154
package/dist/index.mjs
CHANGED
|
@@ -59,7 +59,7 @@ const validateConstructorProperty = (constructor, context) => {
|
|
|
59
59
|
const params = constructor.value.params;
|
|
60
60
|
if (params.length < 2) {
|
|
61
61
|
context.report({
|
|
62
|
-
node: constructor,
|
|
62
|
+
node: constructor.value,
|
|
63
63
|
messageId: "invalidConstructorProperty"
|
|
64
64
|
});
|
|
65
65
|
return;
|
|
@@ -67,7 +67,7 @@ const validateConstructorProperty = (constructor, context) => {
|
|
|
67
67
|
const firstParam = params[0];
|
|
68
68
|
if (firstParam.type === AST_NODE_TYPES.Identifier && firstParam.name !== "scope") {
|
|
69
69
|
context.report({
|
|
70
|
-
node:
|
|
70
|
+
node: firstParam,
|
|
71
71
|
messageId: "invalidConstructorProperty"
|
|
72
72
|
});
|
|
73
73
|
return;
|
|
@@ -75,7 +75,7 @@ const validateConstructorProperty = (constructor, context) => {
|
|
|
75
75
|
const secondParam = params[1];
|
|
76
76
|
if (secondParam.type === AST_NODE_TYPES.Identifier && secondParam.name !== "id") {
|
|
77
77
|
context.report({
|
|
78
|
-
node:
|
|
78
|
+
node: secondParam,
|
|
79
79
|
messageId: "invalidConstructorProperty"
|
|
80
80
|
});
|
|
81
81
|
return;
|
|
@@ -84,29 +84,21 @@ const validateConstructorProperty = (constructor, context) => {
|
|
|
84
84
|
const thirdParam = params[2];
|
|
85
85
|
if (thirdParam.type === AST_NODE_TYPES.Identifier && thirdParam.name !== "props") {
|
|
86
86
|
context.report({
|
|
87
|
-
node:
|
|
87
|
+
node: thirdParam,
|
|
88
88
|
messageId: "invalidConstructorProperty"
|
|
89
89
|
});
|
|
90
90
|
return;
|
|
91
91
|
}
|
|
92
92
|
};
|
|
93
93
|
|
|
94
|
-
const
|
|
95
|
-
CLASS: 32
|
|
96
|
-
};
|
|
97
|
-
const SYNTAX_KIND = {
|
|
98
|
-
CLASS_DECLARATION: 263,
|
|
99
|
-
CONSTRUCTOR: 176
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
const noClassInInterface = ESLintUtils.RuleCreator.withoutDocs({
|
|
94
|
+
const noConstructInInterface = ESLintUtils.RuleCreator.withoutDocs({
|
|
103
95
|
meta: {
|
|
104
96
|
type: "problem",
|
|
105
97
|
docs: {
|
|
106
|
-
description: "Disallow
|
|
98
|
+
description: "Disallow CDK Construct types in interface properties"
|
|
107
99
|
},
|
|
108
100
|
messages: {
|
|
109
|
-
|
|
101
|
+
invalidInterfaceProperty: "Interface property '{{ propertyName }}' should not use CDK Construct type '{{ typeName }}'. Consider using an interface or type alias instead."
|
|
110
102
|
},
|
|
111
103
|
schema: []
|
|
112
104
|
},
|
|
@@ -120,12 +112,10 @@ const noClassInInterface = ESLintUtils.RuleCreator.withoutDocs({
|
|
|
120
112
|
continue;
|
|
121
113
|
}
|
|
122
114
|
const type = parserServices.getTypeAtLocation(property);
|
|
123
|
-
if (!type
|
|
124
|
-
const isClass = type.symbol.flags === SYMBOL_FLAGS.CLASS;
|
|
125
|
-
if (!isClass) continue;
|
|
115
|
+
if (!isConstructOrStackType(type)) continue;
|
|
126
116
|
context.report({
|
|
127
117
|
node: property,
|
|
128
|
-
messageId: "
|
|
118
|
+
messageId: "invalidInterfaceProperty",
|
|
129
119
|
data: {
|
|
130
120
|
propertyName: property.key.name,
|
|
131
121
|
typeName: type.symbol.name
|
|
@@ -137,6 +127,83 @@ const noClassInInterface = ESLintUtils.RuleCreator.withoutDocs({
|
|
|
137
127
|
}
|
|
138
128
|
});
|
|
139
129
|
|
|
130
|
+
const noConstructInPublicPropertyOfConstruct = ESLintUtils.RuleCreator.withoutDocs({
|
|
131
|
+
meta: {
|
|
132
|
+
type: "problem",
|
|
133
|
+
docs: {
|
|
134
|
+
description: "Disallow Construct types in public property of Construct"
|
|
135
|
+
},
|
|
136
|
+
messages: {
|
|
137
|
+
invalidPublicPropertyOfConstruct: "Public property '{{ propertyName }}' of Construct should not use Construct type '{{ typeName }}'. Consider using an interface or type alias instead."
|
|
138
|
+
},
|
|
139
|
+
schema: []
|
|
140
|
+
},
|
|
141
|
+
defaultOptions: [],
|
|
142
|
+
create(context) {
|
|
143
|
+
const parserServices = ESLintUtils.getParserServices(context);
|
|
144
|
+
return {
|
|
145
|
+
ClassDeclaration(node) {
|
|
146
|
+
const type = parserServices.getTypeAtLocation(node);
|
|
147
|
+
if (!isConstructOrStackType(type)) return;
|
|
148
|
+
validatePublicPropertyOfConstruct(node, context, parserServices);
|
|
149
|
+
const constructor = node.body.body.find(
|
|
150
|
+
(member) => member.type === AST_NODE_TYPES.MethodDefinition && member.kind === "constructor"
|
|
151
|
+
);
|
|
152
|
+
if (!constructor || constructor.value.type !== AST_NODE_TYPES.FunctionExpression) {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
validateConstructorParameterProperty(
|
|
156
|
+
constructor,
|
|
157
|
+
context,
|
|
158
|
+
parserServices
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
const validatePublicPropertyOfConstruct = (node, context, parserServices) => {
|
|
165
|
+
for (const property of node.body.body) {
|
|
166
|
+
if (property.type !== AST_NODE_TYPES.PropertyDefinition || property.key.type !== AST_NODE_TYPES.Identifier) {
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
if (["private", "protected"].includes(property.accessibility ?? "")) {
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
if (!property.typeAnnotation) continue;
|
|
173
|
+
const type = parserServices.getTypeAtLocation(property);
|
|
174
|
+
if (!isConstructOrStackType(type)) continue;
|
|
175
|
+
context.report({
|
|
176
|
+
node: property,
|
|
177
|
+
messageId: "invalidPublicPropertyOfConstruct",
|
|
178
|
+
data: {
|
|
179
|
+
propertyName: property.key.name,
|
|
180
|
+
typeName: type.symbol.name
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
const validateConstructorParameterProperty = (constructor, context, parserServices) => {
|
|
186
|
+
for (const param of constructor.value.params) {
|
|
187
|
+
if (param.type !== AST_NODE_TYPES.TSParameterProperty || param.parameter.type !== AST_NODE_TYPES.Identifier) {
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
if (["private", "protected"].includes(param.accessibility ?? "")) {
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
if (!param.parameter.typeAnnotation) continue;
|
|
194
|
+
const type = parserServices.getTypeAtLocation(param);
|
|
195
|
+
if (!isConstructOrStackType(type)) continue;
|
|
196
|
+
context.report({
|
|
197
|
+
node: param,
|
|
198
|
+
messageId: "invalidPublicPropertyOfConstruct",
|
|
199
|
+
data: {
|
|
200
|
+
propertyName: param.parameter.name,
|
|
201
|
+
typeName: type.symbol.name
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
|
|
140
207
|
const toPascalCase = (str) => {
|
|
141
208
|
return str.split(/[-_\s]/).map((word) => {
|
|
142
209
|
return word.replace(/([A-Z])/g, " $1").split(/\s+/).map(
|
|
@@ -145,6 +212,11 @@ const toPascalCase = (str) => {
|
|
|
145
212
|
}).join("");
|
|
146
213
|
};
|
|
147
214
|
|
|
215
|
+
const SYNTAX_KIND = {
|
|
216
|
+
CLASS_DECLARATION: 263,
|
|
217
|
+
CONSTRUCTOR: 176
|
|
218
|
+
};
|
|
219
|
+
|
|
148
220
|
const getConstructorPropertyNames = (type) => {
|
|
149
221
|
const declarations = type.symbol?.declarations;
|
|
150
222
|
if (!declarations?.length) return [];
|
|
@@ -174,7 +246,7 @@ const noConstructStackSuffix = ESLintUtils.RuleCreator.withoutDocs({
|
|
|
174
246
|
description: "Effort to avoid using 'Construct' and 'Stack' suffix in construct id."
|
|
175
247
|
},
|
|
176
248
|
messages: {
|
|
177
|
-
|
|
249
|
+
invalidConstructId: "{{ classType }} ID '{{ id }}' should not include {{ suffix }} suffix."
|
|
178
250
|
},
|
|
179
251
|
schema: [
|
|
180
252
|
{
|
|
@@ -225,8 +297,8 @@ const validateConstructId$3 = (node, context, options) => {
|
|
|
225
297
|
const disallowedSuffixes = options.disallowedSuffixes;
|
|
226
298
|
if (disallowedSuffixes.includes(SUFFIX_TYPE.CONSTRUCT) && formattedConstructId.endsWith(SUFFIX_TYPE.CONSTRUCT)) {
|
|
227
299
|
context.report({
|
|
228
|
-
node,
|
|
229
|
-
messageId: "
|
|
300
|
+
node: secondArg,
|
|
301
|
+
messageId: "invalidConstructId",
|
|
230
302
|
data: {
|
|
231
303
|
classType: "Construct",
|
|
232
304
|
id: secondArg.value,
|
|
@@ -235,8 +307,8 @@ const validateConstructId$3 = (node, context, options) => {
|
|
|
235
307
|
});
|
|
236
308
|
} else if (disallowedSuffixes.includes(SUFFIX_TYPE.STACK) && formattedConstructId.endsWith(SUFFIX_TYPE.STACK)) {
|
|
237
309
|
context.report({
|
|
238
|
-
node,
|
|
239
|
-
messageId: "
|
|
310
|
+
node: secondArg,
|
|
311
|
+
messageId: "invalidConstructId",
|
|
240
312
|
data: {
|
|
241
313
|
classType: "Stack",
|
|
242
314
|
id: secondArg.value,
|
|
@@ -253,7 +325,7 @@ const noImportPrivate = {
|
|
|
253
325
|
description: "Cannot import modules from private dir at different levels of the hierarchy."
|
|
254
326
|
},
|
|
255
327
|
messages: {
|
|
256
|
-
|
|
328
|
+
invalidImportPath: "Cannot import modules from private dir at different levels of the hierarchy."
|
|
257
329
|
},
|
|
258
330
|
schema: []
|
|
259
331
|
},
|
|
@@ -272,7 +344,7 @@ const noImportPrivate = {
|
|
|
272
344
|
if (currentDirSegments.length !== importDirSegments.length || currentDirSegments.some(
|
|
273
345
|
(segment, index) => segment !== importDirSegments[index]
|
|
274
346
|
)) {
|
|
275
|
-
context.report({ node, messageId: "
|
|
347
|
+
context.report({ node, messageId: "invalidImportPath" });
|
|
276
348
|
}
|
|
277
349
|
}
|
|
278
350
|
};
|
|
@@ -282,15 +354,15 @@ const getDirSegments = (dirPath) => {
|
|
|
282
354
|
return dirPath.split(path.sep).filter((segment) => segment !== "");
|
|
283
355
|
};
|
|
284
356
|
|
|
285
|
-
const
|
|
357
|
+
const noMutablePropertyOfPropsInterface = ESLintUtils.RuleCreator.withoutDocs({
|
|
286
358
|
meta: {
|
|
287
359
|
type: "problem",
|
|
288
360
|
docs: {
|
|
289
|
-
description: "Disallow mutable properties
|
|
361
|
+
description: "Disallow mutable properties of Construct Props (interface)"
|
|
290
362
|
},
|
|
291
363
|
fixable: "code",
|
|
292
364
|
messages: {
|
|
293
|
-
|
|
365
|
+
invalidPropertyOfPropsInterface: "Property '{{ propertyName }}' of Construct Props should be readonly."
|
|
294
366
|
},
|
|
295
367
|
schema: []
|
|
296
368
|
},
|
|
@@ -307,7 +379,7 @@ const noMutablePropsInterface = ESLintUtils.RuleCreator.withoutDocs({
|
|
|
307
379
|
if (property.readonly) continue;
|
|
308
380
|
context.report({
|
|
309
381
|
node: property,
|
|
310
|
-
messageId: "
|
|
382
|
+
messageId: "invalidPropertyOfPropsInterface",
|
|
311
383
|
data: {
|
|
312
384
|
propertyName: property.key.name
|
|
313
385
|
},
|
|
@@ -322,15 +394,15 @@ const noMutablePropsInterface = ESLintUtils.RuleCreator.withoutDocs({
|
|
|
322
394
|
}
|
|
323
395
|
});
|
|
324
396
|
|
|
325
|
-
const
|
|
397
|
+
const noMutablePublicPropertyOfConstruct = ESLintUtils.RuleCreator.withoutDocs({
|
|
326
398
|
meta: {
|
|
327
399
|
type: "problem",
|
|
328
400
|
docs: {
|
|
329
|
-
description: "Disallow mutable public
|
|
401
|
+
description: "Disallow mutable public properties of Construct"
|
|
330
402
|
},
|
|
331
403
|
fixable: "code",
|
|
332
404
|
messages: {
|
|
333
|
-
|
|
405
|
+
invalidPublicPropertyOfConstruct: "Public property '{{ propertyName }}' should be readonly. Consider adding the 'readonly' modifier."
|
|
334
406
|
},
|
|
335
407
|
schema: []
|
|
336
408
|
},
|
|
@@ -352,7 +424,7 @@ const noMutablePublicFields = ESLintUtils.RuleCreator.withoutDocs({
|
|
|
352
424
|
if (member.readonly) continue;
|
|
353
425
|
context.report({
|
|
354
426
|
node: member,
|
|
355
|
-
messageId: "
|
|
427
|
+
messageId: "invalidPublicPropertyOfConstruct",
|
|
356
428
|
data: {
|
|
357
429
|
propertyName: member.key.name
|
|
358
430
|
},
|
|
@@ -381,7 +453,7 @@ const noParentNameConstructIdMatch = ESLintUtils.RuleCreator.withoutDocs(
|
|
|
381
453
|
description: "Enforce that construct IDs does not match the parent construct name."
|
|
382
454
|
},
|
|
383
455
|
messages: {
|
|
384
|
-
|
|
456
|
+
invalidConstructId: "Construct ID '{{ constructId }}' should not match parent construct name '{{ parentConstructName }}'. Use a more specific identifier."
|
|
385
457
|
},
|
|
386
458
|
schema: [
|
|
387
459
|
{
|
|
@@ -419,7 +491,6 @@ const noParentNameConstructIdMatch = ESLintUtils.RuleCreator.withoutDocs(
|
|
|
419
491
|
continue;
|
|
420
492
|
}
|
|
421
493
|
validateConstructorBody({
|
|
422
|
-
node,
|
|
423
494
|
expression: body.value,
|
|
424
495
|
parentClassName,
|
|
425
496
|
context,
|
|
@@ -433,7 +504,6 @@ const noParentNameConstructIdMatch = ESLintUtils.RuleCreator.withoutDocs(
|
|
|
433
504
|
}
|
|
434
505
|
);
|
|
435
506
|
const validateConstructorBody = ({
|
|
436
|
-
node,
|
|
437
507
|
expression,
|
|
438
508
|
parentClassName,
|
|
439
509
|
context,
|
|
@@ -446,7 +516,6 @@ const validateConstructorBody = ({
|
|
|
446
516
|
const newExpression = statement.declarations[0].init;
|
|
447
517
|
if (newExpression?.type !== AST_NODE_TYPES.NewExpression) continue;
|
|
448
518
|
validateConstructId$2({
|
|
449
|
-
node,
|
|
450
519
|
context,
|
|
451
520
|
expression: newExpression,
|
|
452
521
|
parentClassName,
|
|
@@ -458,7 +527,6 @@ const validateConstructorBody = ({
|
|
|
458
527
|
case AST_NODE_TYPES.ExpressionStatement: {
|
|
459
528
|
if (statement.expression?.type !== AST_NODE_TYPES.NewExpression) break;
|
|
460
529
|
validateStatement({
|
|
461
|
-
node,
|
|
462
530
|
statement,
|
|
463
531
|
parentClassName,
|
|
464
532
|
context,
|
|
@@ -469,7 +537,6 @@ const validateConstructorBody = ({
|
|
|
469
537
|
}
|
|
470
538
|
case AST_NODE_TYPES.IfStatement: {
|
|
471
539
|
traverseStatements({
|
|
472
|
-
node,
|
|
473
540
|
context,
|
|
474
541
|
parentClassName,
|
|
475
542
|
statement: statement.consequent,
|
|
@@ -482,7 +549,6 @@ const validateConstructorBody = ({
|
|
|
482
549
|
for (const switchCase of statement.cases) {
|
|
483
550
|
for (const statement2 of switchCase.consequent) {
|
|
484
551
|
traverseStatements({
|
|
485
|
-
node,
|
|
486
552
|
context,
|
|
487
553
|
parentClassName,
|
|
488
554
|
statement: statement2,
|
|
@@ -497,7 +563,6 @@ const validateConstructorBody = ({
|
|
|
497
563
|
}
|
|
498
564
|
};
|
|
499
565
|
const traverseStatements = ({
|
|
500
|
-
node,
|
|
501
566
|
statement,
|
|
502
567
|
parentClassName,
|
|
503
568
|
context,
|
|
@@ -508,7 +573,6 @@ const traverseStatements = ({
|
|
|
508
573
|
case AST_NODE_TYPES.BlockStatement: {
|
|
509
574
|
for (const body of statement.body) {
|
|
510
575
|
validateStatement({
|
|
511
|
-
node,
|
|
512
576
|
statement: body,
|
|
513
577
|
parentClassName,
|
|
514
578
|
context,
|
|
@@ -522,7 +586,6 @@ const traverseStatements = ({
|
|
|
522
586
|
const newExpression = statement.expression;
|
|
523
587
|
if (newExpression?.type !== AST_NODE_TYPES.NewExpression) break;
|
|
524
588
|
validateStatement({
|
|
525
|
-
node,
|
|
526
589
|
statement,
|
|
527
590
|
parentClassName,
|
|
528
591
|
context,
|
|
@@ -535,7 +598,6 @@ const traverseStatements = ({
|
|
|
535
598
|
const newExpression = statement.declarations[0].init;
|
|
536
599
|
if (newExpression?.type !== AST_NODE_TYPES.NewExpression) break;
|
|
537
600
|
validateConstructId$2({
|
|
538
|
-
node,
|
|
539
601
|
context,
|
|
540
602
|
expression: newExpression,
|
|
541
603
|
parentClassName,
|
|
@@ -547,7 +609,6 @@ const traverseStatements = ({
|
|
|
547
609
|
}
|
|
548
610
|
};
|
|
549
611
|
const validateStatement = ({
|
|
550
|
-
node,
|
|
551
612
|
statement,
|
|
552
613
|
parentClassName,
|
|
553
614
|
context,
|
|
@@ -559,7 +620,6 @@ const validateStatement = ({
|
|
|
559
620
|
const newExpression = statement.declarations[0].init;
|
|
560
621
|
if (newExpression?.type !== AST_NODE_TYPES.NewExpression) break;
|
|
561
622
|
validateConstructId$2({
|
|
562
|
-
node,
|
|
563
623
|
context,
|
|
564
624
|
expression: newExpression,
|
|
565
625
|
parentClassName,
|
|
@@ -572,7 +632,6 @@ const validateStatement = ({
|
|
|
572
632
|
const newExpression = statement.expression;
|
|
573
633
|
if (newExpression?.type !== AST_NODE_TYPES.NewExpression) break;
|
|
574
634
|
validateConstructId$2({
|
|
575
|
-
node,
|
|
576
635
|
context,
|
|
577
636
|
expression: newExpression,
|
|
578
637
|
parentClassName,
|
|
@@ -583,7 +642,6 @@ const validateStatement = ({
|
|
|
583
642
|
}
|
|
584
643
|
case AST_NODE_TYPES.IfStatement: {
|
|
585
644
|
validateIfStatement({
|
|
586
|
-
node,
|
|
587
645
|
statement,
|
|
588
646
|
parentClassName,
|
|
589
647
|
context,
|
|
@@ -594,7 +652,6 @@ const validateStatement = ({
|
|
|
594
652
|
}
|
|
595
653
|
case AST_NODE_TYPES.SwitchStatement: {
|
|
596
654
|
validateSwitchStatement({
|
|
597
|
-
node,
|
|
598
655
|
statement,
|
|
599
656
|
parentClassName,
|
|
600
657
|
context,
|
|
@@ -606,7 +663,6 @@ const validateStatement = ({
|
|
|
606
663
|
}
|
|
607
664
|
};
|
|
608
665
|
const validateIfStatement = ({
|
|
609
|
-
node,
|
|
610
666
|
statement,
|
|
611
667
|
parentClassName,
|
|
612
668
|
context,
|
|
@@ -614,7 +670,6 @@ const validateIfStatement = ({
|
|
|
614
670
|
option
|
|
615
671
|
}) => {
|
|
616
672
|
traverseStatements({
|
|
617
|
-
node,
|
|
618
673
|
context,
|
|
619
674
|
parentClassName,
|
|
620
675
|
statement: statement.consequent,
|
|
@@ -623,7 +678,6 @@ const validateIfStatement = ({
|
|
|
623
678
|
});
|
|
624
679
|
};
|
|
625
680
|
const validateSwitchStatement = ({
|
|
626
|
-
node,
|
|
627
681
|
statement,
|
|
628
682
|
parentClassName,
|
|
629
683
|
context,
|
|
@@ -633,7 +687,6 @@ const validateSwitchStatement = ({
|
|
|
633
687
|
for (const caseStatement of statement.cases) {
|
|
634
688
|
for (const _consequent of caseStatement.consequent) {
|
|
635
689
|
traverseStatements({
|
|
636
|
-
node,
|
|
637
690
|
context,
|
|
638
691
|
parentClassName,
|
|
639
692
|
statement: _consequent,
|
|
@@ -644,7 +697,6 @@ const validateSwitchStatement = ({
|
|
|
644
697
|
}
|
|
645
698
|
};
|
|
646
699
|
const validateConstructId$2 = ({
|
|
647
|
-
node,
|
|
648
700
|
context,
|
|
649
701
|
expression,
|
|
650
702
|
parentClassName,
|
|
@@ -662,8 +714,8 @@ const validateConstructId$2 = ({
|
|
|
662
714
|
if (!isConstructType(type)) return;
|
|
663
715
|
if (option.disallowContainingParentName && formattedConstructId.includes(formattedParentClassName)) {
|
|
664
716
|
context.report({
|
|
665
|
-
node,
|
|
666
|
-
messageId: "
|
|
717
|
+
node: secondArg,
|
|
718
|
+
messageId: "invalidConstructId",
|
|
667
719
|
data: {
|
|
668
720
|
constructId: secondArg.value,
|
|
669
721
|
parentConstructName: parentClassName
|
|
@@ -673,8 +725,8 @@ const validateConstructId$2 = ({
|
|
|
673
725
|
}
|
|
674
726
|
if (formattedParentClassName === formattedConstructId) {
|
|
675
727
|
context.report({
|
|
676
|
-
node,
|
|
677
|
-
messageId: "
|
|
728
|
+
node: secondArg,
|
|
729
|
+
messageId: "invalidConstructId",
|
|
678
730
|
data: {
|
|
679
731
|
constructId: secondArg.value,
|
|
680
732
|
parentConstructName: parentClassName
|
|
@@ -683,87 +735,6 @@ const validateConstructId$2 = ({
|
|
|
683
735
|
}
|
|
684
736
|
};
|
|
685
737
|
|
|
686
|
-
const noPublicClassFields = ESLintUtils.RuleCreator.withoutDocs({
|
|
687
|
-
meta: {
|
|
688
|
-
type: "problem",
|
|
689
|
-
docs: {
|
|
690
|
-
description: "Disallow class types in public class fields"
|
|
691
|
-
},
|
|
692
|
-
messages: {
|
|
693
|
-
noPublicClassFields: "Public field '{{ propertyName }}' should not use class type '{{ typeName }}'. Consider using an interface or type alias instead."
|
|
694
|
-
},
|
|
695
|
-
schema: []
|
|
696
|
-
},
|
|
697
|
-
defaultOptions: [],
|
|
698
|
-
create(context) {
|
|
699
|
-
const parserServices = ESLintUtils.getParserServices(context);
|
|
700
|
-
return {
|
|
701
|
-
ClassDeclaration(node) {
|
|
702
|
-
const type = parserServices.getTypeAtLocation(node);
|
|
703
|
-
if (!isConstructOrStackType(type)) return;
|
|
704
|
-
validateClassMember(node, context, parserServices);
|
|
705
|
-
const constructor = node.body.body.find(
|
|
706
|
-
(member) => member.type === AST_NODE_TYPES.MethodDefinition && member.kind === "constructor"
|
|
707
|
-
);
|
|
708
|
-
if (!constructor || constructor.value.type !== AST_NODE_TYPES.FunctionExpression) {
|
|
709
|
-
return;
|
|
710
|
-
}
|
|
711
|
-
validateConstructorParameterProperty(
|
|
712
|
-
constructor,
|
|
713
|
-
context,
|
|
714
|
-
parserServices
|
|
715
|
-
);
|
|
716
|
-
}
|
|
717
|
-
};
|
|
718
|
-
}
|
|
719
|
-
});
|
|
720
|
-
const validateClassMember = (node, context, parserServices) => {
|
|
721
|
-
for (const member of node.body.body) {
|
|
722
|
-
if (member.type !== AST_NODE_TYPES.PropertyDefinition || member.key.type !== AST_NODE_TYPES.Identifier) {
|
|
723
|
-
continue;
|
|
724
|
-
}
|
|
725
|
-
if (["private", "protected"].includes(member.accessibility ?? "")) {
|
|
726
|
-
continue;
|
|
727
|
-
}
|
|
728
|
-
if (!member.typeAnnotation) continue;
|
|
729
|
-
const type = parserServices.getTypeAtLocation(member);
|
|
730
|
-
if (!type.symbol) continue;
|
|
731
|
-
const isClass = type.symbol.flags === SYMBOL_FLAGS.CLASS;
|
|
732
|
-
if (!isClass) continue;
|
|
733
|
-
context.report({
|
|
734
|
-
node: member,
|
|
735
|
-
messageId: "noPublicClassFields",
|
|
736
|
-
data: {
|
|
737
|
-
propertyName: member.key.name,
|
|
738
|
-
typeName: type.symbol.name
|
|
739
|
-
}
|
|
740
|
-
});
|
|
741
|
-
}
|
|
742
|
-
};
|
|
743
|
-
const validateConstructorParameterProperty = (constructor, context, parserServices) => {
|
|
744
|
-
for (const param of constructor.value.params) {
|
|
745
|
-
if (param.type !== AST_NODE_TYPES.TSParameterProperty || param.parameter.type !== AST_NODE_TYPES.Identifier) {
|
|
746
|
-
continue;
|
|
747
|
-
}
|
|
748
|
-
if (["private", "protected"].includes(param.accessibility ?? "")) {
|
|
749
|
-
continue;
|
|
750
|
-
}
|
|
751
|
-
if (!param.parameter.typeAnnotation) continue;
|
|
752
|
-
const type = parserServices.getTypeAtLocation(param);
|
|
753
|
-
if (!type.symbol) continue;
|
|
754
|
-
const isClass = type.symbol.flags === SYMBOL_FLAGS.CLASS;
|
|
755
|
-
if (!isClass) continue;
|
|
756
|
-
context.report({
|
|
757
|
-
node: param,
|
|
758
|
-
messageId: "noPublicClassFields",
|
|
759
|
-
data: {
|
|
760
|
-
propertyName: param.parameter.name,
|
|
761
|
-
typeName: type.symbol.name
|
|
762
|
-
}
|
|
763
|
-
});
|
|
764
|
-
}
|
|
765
|
-
};
|
|
766
|
-
|
|
767
738
|
const noVariableConstructId = ESLintUtils.RuleCreator.withoutDocs({
|
|
768
739
|
meta: {
|
|
769
740
|
type: "problem",
|
|
@@ -771,7 +742,7 @@ const noVariableConstructId = ESLintUtils.RuleCreator.withoutDocs({
|
|
|
771
742
|
description: `Enforce using literal strings for Construct ID.`
|
|
772
743
|
},
|
|
773
744
|
messages: {
|
|
774
|
-
|
|
745
|
+
invalidConstructId: "Shouldn't use a parameter as a Construct ID."
|
|
775
746
|
},
|
|
776
747
|
schema: []
|
|
777
748
|
},
|
|
@@ -799,8 +770,8 @@ const validateConstructId$1 = (node, context) => {
|
|
|
799
770
|
return;
|
|
800
771
|
}
|
|
801
772
|
context.report({
|
|
802
|
-
node,
|
|
803
|
-
messageId: "
|
|
773
|
+
node: secondArg,
|
|
774
|
+
messageId: "invalidConstructId"
|
|
804
775
|
});
|
|
805
776
|
};
|
|
806
777
|
const isInsideLoop = (node) => {
|
|
@@ -836,7 +807,7 @@ const pascalCaseConstructId = ESLintUtils.RuleCreator.withoutDocs({
|
|
|
836
807
|
description: "Enforce PascalCase for Construct ID."
|
|
837
808
|
},
|
|
838
809
|
messages: {
|
|
839
|
-
|
|
810
|
+
invalidConstructId: "Construct ID must be PascalCase."
|
|
840
811
|
},
|
|
841
812
|
schema: [],
|
|
842
813
|
fixable: "code"
|
|
@@ -869,8 +840,8 @@ const validateConstructId = (node, context) => {
|
|
|
869
840
|
const quote = secondArg.raw?.startsWith('"') ? QUOTE_TYPE.DOUBLE : QUOTE_TYPE.SINGLE;
|
|
870
841
|
if (isPascalCase(secondArg.value)) return;
|
|
871
842
|
context.report({
|
|
872
|
-
node,
|
|
873
|
-
messageId: "
|
|
843
|
+
node: secondArg,
|
|
844
|
+
messageId: "invalidConstructId",
|
|
874
845
|
fix: (fixer) => {
|
|
875
846
|
const pascalCaseValue = toPascalCase(secondArg.value);
|
|
876
847
|
return fixer.replaceText(secondArg, `${quote}${pascalCaseValue}${quote}`);
|
|
@@ -997,7 +968,7 @@ const requirePassingThis = ESLintUtils.RuleCreator.withoutDocs({
|
|
|
997
968
|
description: "Require passing `this` in a constructor."
|
|
998
969
|
},
|
|
999
970
|
messages: {
|
|
1000
|
-
|
|
971
|
+
missingPassingThis: "Require passing `this` in a constructor."
|
|
1001
972
|
},
|
|
1002
973
|
schema: [
|
|
1003
974
|
{
|
|
@@ -1033,8 +1004,8 @@ const requirePassingThis = ESLintUtils.RuleCreator.withoutDocs({
|
|
|
1033
1004
|
if (constructorPropertyNames[0] !== "scope") return;
|
|
1034
1005
|
if (!options.allowNonThisAndDisallowScope) {
|
|
1035
1006
|
context.report({
|
|
1036
|
-
node,
|
|
1037
|
-
messageId: "
|
|
1007
|
+
node: argument,
|
|
1008
|
+
messageId: "missingPassingThis",
|
|
1038
1009
|
fix: (fixer) => {
|
|
1039
1010
|
return fixer.replaceText(argument, "this");
|
|
1040
1011
|
}
|
|
@@ -1043,8 +1014,8 @@ const requirePassingThis = ESLintUtils.RuleCreator.withoutDocs({
|
|
|
1043
1014
|
}
|
|
1044
1015
|
if (argument.type === AST_NODE_TYPES.Identifier && argument.name === "scope") {
|
|
1045
1016
|
context.report({
|
|
1046
|
-
node,
|
|
1047
|
-
messageId: "
|
|
1017
|
+
node: argument,
|
|
1018
|
+
messageId: "missingPassingThis",
|
|
1048
1019
|
fix: (fixer) => {
|
|
1049
1020
|
return fixer.replaceText(argument, "this");
|
|
1050
1021
|
}
|
|
@@ -1098,20 +1069,20 @@ const requirePropsDefaultDoc = ESLintUtils.RuleCreator.withoutDocs({
|
|
|
1098
1069
|
});
|
|
1099
1070
|
|
|
1100
1071
|
const rules = {
|
|
1101
|
-
"
|
|
1072
|
+
"construct-constructor-property": constructConstructorProperty,
|
|
1073
|
+
"no-construct-in-interface": noConstructInInterface,
|
|
1074
|
+
"no-construct-in-public-property-of-construct": noConstructInPublicPropertyOfConstruct,
|
|
1102
1075
|
"no-construct-stack-suffix": noConstructStackSuffix,
|
|
1076
|
+
"no-import-private": noImportPrivate,
|
|
1077
|
+
"no-mutable-property-of-props-interface": noMutablePropertyOfPropsInterface,
|
|
1078
|
+
"no-mutable-public-property-of-construct": noMutablePublicPropertyOfConstruct,
|
|
1103
1079
|
"no-parent-name-construct-id-match": noParentNameConstructIdMatch,
|
|
1104
|
-
"no-public-class-fields": noPublicClassFields,
|
|
1105
|
-
"pascal-case-construct-id": pascalCaseConstructId,
|
|
1106
|
-
"require-passing-this": requirePassingThis,
|
|
1107
1080
|
"no-variable-construct-id": noVariableConstructId,
|
|
1108
|
-
"
|
|
1109
|
-
"no-mutable-props-interface": noMutablePropsInterface,
|
|
1110
|
-
"construct-constructor-property": constructConstructorProperty,
|
|
1111
|
-
"require-jsdoc": requireJSDoc,
|
|
1112
|
-
"require-props-default-doc": requirePropsDefaultDoc,
|
|
1081
|
+
"pascal-case-construct-id": pascalCaseConstructId,
|
|
1113
1082
|
"props-name-convention": propsNameConvention,
|
|
1114
|
-
"
|
|
1083
|
+
"require-jsdoc": requireJSDoc,
|
|
1084
|
+
"require-passing-this": requirePassingThis,
|
|
1085
|
+
"require-props-default-doc": requirePropsDefaultDoc
|
|
1115
1086
|
};
|
|
1116
1087
|
const cdkPlugin = {
|
|
1117
1088
|
meta: { name, version },
|
|
@@ -1132,38 +1103,38 @@ const createFlatConfig = (rules2) => {
|
|
|
1132
1103
|
};
|
|
1133
1104
|
};
|
|
1134
1105
|
const recommended = createFlatConfig({
|
|
1135
|
-
"cdk/
|
|
1106
|
+
"cdk/construct-constructor-property": "error",
|
|
1107
|
+
"cdk/no-construct-in-interface": "error",
|
|
1108
|
+
"cdk/no-construct-in-public-property-of-construct": "error",
|
|
1136
1109
|
"cdk/no-construct-stack-suffix": "error",
|
|
1110
|
+
"cdk/no-mutable-property-of-props-interface": "warn",
|
|
1111
|
+
"cdk/no-mutable-public-property-of-construct": "warn",
|
|
1137
1112
|
"cdk/no-parent-name-construct-id-match": [
|
|
1138
1113
|
"error",
|
|
1139
1114
|
{ disallowContainingParentName: false }
|
|
1140
1115
|
],
|
|
1141
|
-
"cdk/no-public-class-fields": "error",
|
|
1142
|
-
"cdk/pascal-case-construct-id": "error",
|
|
1143
|
-
"cdk/require-passing-this": ["error", { allowNonThisAndDisallowScope: true }],
|
|
1144
1116
|
"cdk/no-variable-construct-id": "error",
|
|
1145
|
-
"cdk/
|
|
1146
|
-
"cdk/
|
|
1147
|
-
"cdk/construct-constructor-property": "error"
|
|
1117
|
+
"cdk/pascal-case-construct-id": "error",
|
|
1118
|
+
"cdk/require-passing-this": ["error", { allowNonThisAndDisallowScope: true }]
|
|
1148
1119
|
});
|
|
1149
1120
|
const strict = createFlatConfig({
|
|
1150
|
-
"cdk/
|
|
1121
|
+
"cdk/construct-constructor-property": "error",
|
|
1122
|
+
"cdk/no-construct-in-interface": "error",
|
|
1123
|
+
"cdk/no-construct-in-public-property-of-construct": "error",
|
|
1151
1124
|
"cdk/no-construct-stack-suffix": "error",
|
|
1125
|
+
"cdk/no-import-private": "error",
|
|
1126
|
+
"cdk/no-mutable-property-of-props-interface": "error",
|
|
1127
|
+
"cdk/no-mutable-public-property-of-construct": "error",
|
|
1152
1128
|
"cdk/no-parent-name-construct-id-match": [
|
|
1153
1129
|
"error",
|
|
1154
1130
|
{ disallowContainingParentName: true }
|
|
1155
1131
|
],
|
|
1156
|
-
"cdk/no-public-class-fields": "error",
|
|
1157
|
-
"cdk/pascal-case-construct-id": "error",
|
|
1158
|
-
"cdk/require-passing-this": "error",
|
|
1159
1132
|
"cdk/no-variable-construct-id": "error",
|
|
1160
|
-
"cdk/
|
|
1161
|
-
"cdk/no-mutable-props-interface": "error",
|
|
1162
|
-
"cdk/construct-constructor-property": "error",
|
|
1163
|
-
"cdk/require-jsdoc": "error",
|
|
1164
|
-
"cdk/require-props-default-doc": "error",
|
|
1133
|
+
"cdk/pascal-case-construct-id": "error",
|
|
1165
1134
|
"cdk/props-name-convention": "error",
|
|
1166
|
-
"cdk/
|
|
1135
|
+
"cdk/require-jsdoc": "error",
|
|
1136
|
+
"cdk/require-passing-this": "error",
|
|
1137
|
+
"cdk/require-props-default-doc": "error"
|
|
1167
1138
|
});
|
|
1168
1139
|
const configs = {
|
|
1169
1140
|
recommended,
|