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.cjs
CHANGED
|
@@ -82,7 +82,7 @@ const validateConstructorProperty = (constructor, context) => {
|
|
|
82
82
|
const params = constructor.value.params;
|
|
83
83
|
if (params.length < 2) {
|
|
84
84
|
context.report({
|
|
85
|
-
node: constructor,
|
|
85
|
+
node: constructor.value,
|
|
86
86
|
messageId: "invalidConstructorProperty"
|
|
87
87
|
});
|
|
88
88
|
return;
|
|
@@ -90,7 +90,7 @@ const validateConstructorProperty = (constructor, context) => {
|
|
|
90
90
|
const firstParam = params[0];
|
|
91
91
|
if (firstParam.type === utils.AST_NODE_TYPES.Identifier && firstParam.name !== "scope") {
|
|
92
92
|
context.report({
|
|
93
|
-
node:
|
|
93
|
+
node: firstParam,
|
|
94
94
|
messageId: "invalidConstructorProperty"
|
|
95
95
|
});
|
|
96
96
|
return;
|
|
@@ -98,7 +98,7 @@ const validateConstructorProperty = (constructor, context) => {
|
|
|
98
98
|
const secondParam = params[1];
|
|
99
99
|
if (secondParam.type === utils.AST_NODE_TYPES.Identifier && secondParam.name !== "id") {
|
|
100
100
|
context.report({
|
|
101
|
-
node:
|
|
101
|
+
node: secondParam,
|
|
102
102
|
messageId: "invalidConstructorProperty"
|
|
103
103
|
});
|
|
104
104
|
return;
|
|
@@ -107,29 +107,21 @@ const validateConstructorProperty = (constructor, context) => {
|
|
|
107
107
|
const thirdParam = params[2];
|
|
108
108
|
if (thirdParam.type === utils.AST_NODE_TYPES.Identifier && thirdParam.name !== "props") {
|
|
109
109
|
context.report({
|
|
110
|
-
node:
|
|
110
|
+
node: thirdParam,
|
|
111
111
|
messageId: "invalidConstructorProperty"
|
|
112
112
|
});
|
|
113
113
|
return;
|
|
114
114
|
}
|
|
115
115
|
};
|
|
116
116
|
|
|
117
|
-
const
|
|
118
|
-
CLASS: 32
|
|
119
|
-
};
|
|
120
|
-
const SYNTAX_KIND = {
|
|
121
|
-
CLASS_DECLARATION: 263,
|
|
122
|
-
CONSTRUCTOR: 176
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
const noClassInInterface = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
117
|
+
const noConstructInInterface = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
126
118
|
meta: {
|
|
127
119
|
type: "problem",
|
|
128
120
|
docs: {
|
|
129
|
-
description: "Disallow
|
|
121
|
+
description: "Disallow CDK Construct types in interface properties"
|
|
130
122
|
},
|
|
131
123
|
messages: {
|
|
132
|
-
|
|
124
|
+
invalidInterfaceProperty: "Interface property '{{ propertyName }}' should not use CDK Construct type '{{ typeName }}'. Consider using an interface or type alias instead."
|
|
133
125
|
},
|
|
134
126
|
schema: []
|
|
135
127
|
},
|
|
@@ -143,12 +135,10 @@ const noClassInInterface = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
|
143
135
|
continue;
|
|
144
136
|
}
|
|
145
137
|
const type = parserServices.getTypeAtLocation(property);
|
|
146
|
-
if (!type
|
|
147
|
-
const isClass = type.symbol.flags === SYMBOL_FLAGS.CLASS;
|
|
148
|
-
if (!isClass) continue;
|
|
138
|
+
if (!isConstructOrStackType(type)) continue;
|
|
149
139
|
context.report({
|
|
150
140
|
node: property,
|
|
151
|
-
messageId: "
|
|
141
|
+
messageId: "invalidInterfaceProperty",
|
|
152
142
|
data: {
|
|
153
143
|
propertyName: property.key.name,
|
|
154
144
|
typeName: type.symbol.name
|
|
@@ -160,6 +150,83 @@ const noClassInInterface = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
|
160
150
|
}
|
|
161
151
|
});
|
|
162
152
|
|
|
153
|
+
const noConstructInPublicPropertyOfConstruct = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
154
|
+
meta: {
|
|
155
|
+
type: "problem",
|
|
156
|
+
docs: {
|
|
157
|
+
description: "Disallow Construct types in public property of Construct"
|
|
158
|
+
},
|
|
159
|
+
messages: {
|
|
160
|
+
invalidPublicPropertyOfConstruct: "Public property '{{ propertyName }}' of Construct should not use Construct type '{{ typeName }}'. Consider using an interface or type alias instead."
|
|
161
|
+
},
|
|
162
|
+
schema: []
|
|
163
|
+
},
|
|
164
|
+
defaultOptions: [],
|
|
165
|
+
create(context) {
|
|
166
|
+
const parserServices = utils.ESLintUtils.getParserServices(context);
|
|
167
|
+
return {
|
|
168
|
+
ClassDeclaration(node) {
|
|
169
|
+
const type = parserServices.getTypeAtLocation(node);
|
|
170
|
+
if (!isConstructOrStackType(type)) return;
|
|
171
|
+
validatePublicPropertyOfConstruct(node, context, parserServices);
|
|
172
|
+
const constructor = node.body.body.find(
|
|
173
|
+
(member) => member.type === utils.AST_NODE_TYPES.MethodDefinition && member.kind === "constructor"
|
|
174
|
+
);
|
|
175
|
+
if (!constructor || constructor.value.type !== utils.AST_NODE_TYPES.FunctionExpression) {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
validateConstructorParameterProperty(
|
|
179
|
+
constructor,
|
|
180
|
+
context,
|
|
181
|
+
parserServices
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
const validatePublicPropertyOfConstruct = (node, context, parserServices) => {
|
|
188
|
+
for (const property of node.body.body) {
|
|
189
|
+
if (property.type !== utils.AST_NODE_TYPES.PropertyDefinition || property.key.type !== utils.AST_NODE_TYPES.Identifier) {
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
if (["private", "protected"].includes(property.accessibility ?? "")) {
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
if (!property.typeAnnotation) continue;
|
|
196
|
+
const type = parserServices.getTypeAtLocation(property);
|
|
197
|
+
if (!isConstructOrStackType(type)) continue;
|
|
198
|
+
context.report({
|
|
199
|
+
node: property,
|
|
200
|
+
messageId: "invalidPublicPropertyOfConstruct",
|
|
201
|
+
data: {
|
|
202
|
+
propertyName: property.key.name,
|
|
203
|
+
typeName: type.symbol.name
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
const validateConstructorParameterProperty = (constructor, context, parserServices) => {
|
|
209
|
+
for (const param of constructor.value.params) {
|
|
210
|
+
if (param.type !== utils.AST_NODE_TYPES.TSParameterProperty || param.parameter.type !== utils.AST_NODE_TYPES.Identifier) {
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
if (["private", "protected"].includes(param.accessibility ?? "")) {
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
216
|
+
if (!param.parameter.typeAnnotation) continue;
|
|
217
|
+
const type = parserServices.getTypeAtLocation(param);
|
|
218
|
+
if (!isConstructOrStackType(type)) continue;
|
|
219
|
+
context.report({
|
|
220
|
+
node: param,
|
|
221
|
+
messageId: "invalidPublicPropertyOfConstruct",
|
|
222
|
+
data: {
|
|
223
|
+
propertyName: param.parameter.name,
|
|
224
|
+
typeName: type.symbol.name
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
|
|
163
230
|
const toPascalCase = (str) => {
|
|
164
231
|
return str.split(/[-_\s]/).map((word) => {
|
|
165
232
|
return word.replace(/([A-Z])/g, " $1").split(/\s+/).map(
|
|
@@ -168,6 +235,11 @@ const toPascalCase = (str) => {
|
|
|
168
235
|
}).join("");
|
|
169
236
|
};
|
|
170
237
|
|
|
238
|
+
const SYNTAX_KIND = {
|
|
239
|
+
CLASS_DECLARATION: 263,
|
|
240
|
+
CONSTRUCTOR: 176
|
|
241
|
+
};
|
|
242
|
+
|
|
171
243
|
const getConstructorPropertyNames = (type) => {
|
|
172
244
|
const declarations = type.symbol?.declarations;
|
|
173
245
|
if (!declarations?.length) return [];
|
|
@@ -197,7 +269,7 @@ const noConstructStackSuffix = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
|
197
269
|
description: "Effort to avoid using 'Construct' and 'Stack' suffix in construct id."
|
|
198
270
|
},
|
|
199
271
|
messages: {
|
|
200
|
-
|
|
272
|
+
invalidConstructId: "{{ classType }} ID '{{ id }}' should not include {{ suffix }} suffix."
|
|
201
273
|
},
|
|
202
274
|
schema: [
|
|
203
275
|
{
|
|
@@ -248,8 +320,8 @@ const validateConstructId$3 = (node, context, options) => {
|
|
|
248
320
|
const disallowedSuffixes = options.disallowedSuffixes;
|
|
249
321
|
if (disallowedSuffixes.includes(SUFFIX_TYPE.CONSTRUCT) && formattedConstructId.endsWith(SUFFIX_TYPE.CONSTRUCT)) {
|
|
250
322
|
context.report({
|
|
251
|
-
node,
|
|
252
|
-
messageId: "
|
|
323
|
+
node: secondArg,
|
|
324
|
+
messageId: "invalidConstructId",
|
|
253
325
|
data: {
|
|
254
326
|
classType: "Construct",
|
|
255
327
|
id: secondArg.value,
|
|
@@ -258,8 +330,8 @@ const validateConstructId$3 = (node, context, options) => {
|
|
|
258
330
|
});
|
|
259
331
|
} else if (disallowedSuffixes.includes(SUFFIX_TYPE.STACK) && formattedConstructId.endsWith(SUFFIX_TYPE.STACK)) {
|
|
260
332
|
context.report({
|
|
261
|
-
node,
|
|
262
|
-
messageId: "
|
|
333
|
+
node: secondArg,
|
|
334
|
+
messageId: "invalidConstructId",
|
|
263
335
|
data: {
|
|
264
336
|
classType: "Stack",
|
|
265
337
|
id: secondArg.value,
|
|
@@ -276,7 +348,7 @@ const noImportPrivate = {
|
|
|
276
348
|
description: "Cannot import modules from private dir at different levels of the hierarchy."
|
|
277
349
|
},
|
|
278
350
|
messages: {
|
|
279
|
-
|
|
351
|
+
invalidImportPath: "Cannot import modules from private dir at different levels of the hierarchy."
|
|
280
352
|
},
|
|
281
353
|
schema: []
|
|
282
354
|
},
|
|
@@ -295,7 +367,7 @@ const noImportPrivate = {
|
|
|
295
367
|
if (currentDirSegments.length !== importDirSegments.length || currentDirSegments.some(
|
|
296
368
|
(segment, index) => segment !== importDirSegments[index]
|
|
297
369
|
)) {
|
|
298
|
-
context.report({ node, messageId: "
|
|
370
|
+
context.report({ node, messageId: "invalidImportPath" });
|
|
299
371
|
}
|
|
300
372
|
}
|
|
301
373
|
};
|
|
@@ -305,15 +377,15 @@ const getDirSegments = (dirPath) => {
|
|
|
305
377
|
return dirPath.split(path__namespace.sep).filter((segment) => segment !== "");
|
|
306
378
|
};
|
|
307
379
|
|
|
308
|
-
const
|
|
380
|
+
const noMutablePropertyOfPropsInterface = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
309
381
|
meta: {
|
|
310
382
|
type: "problem",
|
|
311
383
|
docs: {
|
|
312
|
-
description: "Disallow mutable properties
|
|
384
|
+
description: "Disallow mutable properties of Construct Props (interface)"
|
|
313
385
|
},
|
|
314
386
|
fixable: "code",
|
|
315
387
|
messages: {
|
|
316
|
-
|
|
388
|
+
invalidPropertyOfPropsInterface: "Property '{{ propertyName }}' of Construct Props should be readonly."
|
|
317
389
|
},
|
|
318
390
|
schema: []
|
|
319
391
|
},
|
|
@@ -330,7 +402,7 @@ const noMutablePropsInterface = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
|
330
402
|
if (property.readonly) continue;
|
|
331
403
|
context.report({
|
|
332
404
|
node: property,
|
|
333
|
-
messageId: "
|
|
405
|
+
messageId: "invalidPropertyOfPropsInterface",
|
|
334
406
|
data: {
|
|
335
407
|
propertyName: property.key.name
|
|
336
408
|
},
|
|
@@ -345,15 +417,15 @@ const noMutablePropsInterface = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
|
345
417
|
}
|
|
346
418
|
});
|
|
347
419
|
|
|
348
|
-
const
|
|
420
|
+
const noMutablePublicPropertyOfConstruct = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
349
421
|
meta: {
|
|
350
422
|
type: "problem",
|
|
351
423
|
docs: {
|
|
352
|
-
description: "Disallow mutable public
|
|
424
|
+
description: "Disallow mutable public properties of Construct"
|
|
353
425
|
},
|
|
354
426
|
fixable: "code",
|
|
355
427
|
messages: {
|
|
356
|
-
|
|
428
|
+
invalidPublicPropertyOfConstruct: "Public property '{{ propertyName }}' should be readonly. Consider adding the 'readonly' modifier."
|
|
357
429
|
},
|
|
358
430
|
schema: []
|
|
359
431
|
},
|
|
@@ -375,7 +447,7 @@ const noMutablePublicFields = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
|
375
447
|
if (member.readonly) continue;
|
|
376
448
|
context.report({
|
|
377
449
|
node: member,
|
|
378
|
-
messageId: "
|
|
450
|
+
messageId: "invalidPublicPropertyOfConstruct",
|
|
379
451
|
data: {
|
|
380
452
|
propertyName: member.key.name
|
|
381
453
|
},
|
|
@@ -404,7 +476,7 @@ const noParentNameConstructIdMatch = utils.ESLintUtils.RuleCreator.withoutDocs(
|
|
|
404
476
|
description: "Enforce that construct IDs does not match the parent construct name."
|
|
405
477
|
},
|
|
406
478
|
messages: {
|
|
407
|
-
|
|
479
|
+
invalidConstructId: "Construct ID '{{ constructId }}' should not match parent construct name '{{ parentConstructName }}'. Use a more specific identifier."
|
|
408
480
|
},
|
|
409
481
|
schema: [
|
|
410
482
|
{
|
|
@@ -442,7 +514,6 @@ const noParentNameConstructIdMatch = utils.ESLintUtils.RuleCreator.withoutDocs(
|
|
|
442
514
|
continue;
|
|
443
515
|
}
|
|
444
516
|
validateConstructorBody({
|
|
445
|
-
node,
|
|
446
517
|
expression: body.value,
|
|
447
518
|
parentClassName,
|
|
448
519
|
context,
|
|
@@ -456,7 +527,6 @@ const noParentNameConstructIdMatch = utils.ESLintUtils.RuleCreator.withoutDocs(
|
|
|
456
527
|
}
|
|
457
528
|
);
|
|
458
529
|
const validateConstructorBody = ({
|
|
459
|
-
node,
|
|
460
530
|
expression,
|
|
461
531
|
parentClassName,
|
|
462
532
|
context,
|
|
@@ -469,7 +539,6 @@ const validateConstructorBody = ({
|
|
|
469
539
|
const newExpression = statement.declarations[0].init;
|
|
470
540
|
if (newExpression?.type !== utils.AST_NODE_TYPES.NewExpression) continue;
|
|
471
541
|
validateConstructId$2({
|
|
472
|
-
node,
|
|
473
542
|
context,
|
|
474
543
|
expression: newExpression,
|
|
475
544
|
parentClassName,
|
|
@@ -481,7 +550,6 @@ const validateConstructorBody = ({
|
|
|
481
550
|
case utils.AST_NODE_TYPES.ExpressionStatement: {
|
|
482
551
|
if (statement.expression?.type !== utils.AST_NODE_TYPES.NewExpression) break;
|
|
483
552
|
validateStatement({
|
|
484
|
-
node,
|
|
485
553
|
statement,
|
|
486
554
|
parentClassName,
|
|
487
555
|
context,
|
|
@@ -492,7 +560,6 @@ const validateConstructorBody = ({
|
|
|
492
560
|
}
|
|
493
561
|
case utils.AST_NODE_TYPES.IfStatement: {
|
|
494
562
|
traverseStatements({
|
|
495
|
-
node,
|
|
496
563
|
context,
|
|
497
564
|
parentClassName,
|
|
498
565
|
statement: statement.consequent,
|
|
@@ -505,7 +572,6 @@ const validateConstructorBody = ({
|
|
|
505
572
|
for (const switchCase of statement.cases) {
|
|
506
573
|
for (const statement2 of switchCase.consequent) {
|
|
507
574
|
traverseStatements({
|
|
508
|
-
node,
|
|
509
575
|
context,
|
|
510
576
|
parentClassName,
|
|
511
577
|
statement: statement2,
|
|
@@ -520,7 +586,6 @@ const validateConstructorBody = ({
|
|
|
520
586
|
}
|
|
521
587
|
};
|
|
522
588
|
const traverseStatements = ({
|
|
523
|
-
node,
|
|
524
589
|
statement,
|
|
525
590
|
parentClassName,
|
|
526
591
|
context,
|
|
@@ -531,7 +596,6 @@ const traverseStatements = ({
|
|
|
531
596
|
case utils.AST_NODE_TYPES.BlockStatement: {
|
|
532
597
|
for (const body of statement.body) {
|
|
533
598
|
validateStatement({
|
|
534
|
-
node,
|
|
535
599
|
statement: body,
|
|
536
600
|
parentClassName,
|
|
537
601
|
context,
|
|
@@ -545,7 +609,6 @@ const traverseStatements = ({
|
|
|
545
609
|
const newExpression = statement.expression;
|
|
546
610
|
if (newExpression?.type !== utils.AST_NODE_TYPES.NewExpression) break;
|
|
547
611
|
validateStatement({
|
|
548
|
-
node,
|
|
549
612
|
statement,
|
|
550
613
|
parentClassName,
|
|
551
614
|
context,
|
|
@@ -558,7 +621,6 @@ const traverseStatements = ({
|
|
|
558
621
|
const newExpression = statement.declarations[0].init;
|
|
559
622
|
if (newExpression?.type !== utils.AST_NODE_TYPES.NewExpression) break;
|
|
560
623
|
validateConstructId$2({
|
|
561
|
-
node,
|
|
562
624
|
context,
|
|
563
625
|
expression: newExpression,
|
|
564
626
|
parentClassName,
|
|
@@ -570,7 +632,6 @@ const traverseStatements = ({
|
|
|
570
632
|
}
|
|
571
633
|
};
|
|
572
634
|
const validateStatement = ({
|
|
573
|
-
node,
|
|
574
635
|
statement,
|
|
575
636
|
parentClassName,
|
|
576
637
|
context,
|
|
@@ -582,7 +643,6 @@ const validateStatement = ({
|
|
|
582
643
|
const newExpression = statement.declarations[0].init;
|
|
583
644
|
if (newExpression?.type !== utils.AST_NODE_TYPES.NewExpression) break;
|
|
584
645
|
validateConstructId$2({
|
|
585
|
-
node,
|
|
586
646
|
context,
|
|
587
647
|
expression: newExpression,
|
|
588
648
|
parentClassName,
|
|
@@ -595,7 +655,6 @@ const validateStatement = ({
|
|
|
595
655
|
const newExpression = statement.expression;
|
|
596
656
|
if (newExpression?.type !== utils.AST_NODE_TYPES.NewExpression) break;
|
|
597
657
|
validateConstructId$2({
|
|
598
|
-
node,
|
|
599
658
|
context,
|
|
600
659
|
expression: newExpression,
|
|
601
660
|
parentClassName,
|
|
@@ -606,7 +665,6 @@ const validateStatement = ({
|
|
|
606
665
|
}
|
|
607
666
|
case utils.AST_NODE_TYPES.IfStatement: {
|
|
608
667
|
validateIfStatement({
|
|
609
|
-
node,
|
|
610
668
|
statement,
|
|
611
669
|
parentClassName,
|
|
612
670
|
context,
|
|
@@ -617,7 +675,6 @@ const validateStatement = ({
|
|
|
617
675
|
}
|
|
618
676
|
case utils.AST_NODE_TYPES.SwitchStatement: {
|
|
619
677
|
validateSwitchStatement({
|
|
620
|
-
node,
|
|
621
678
|
statement,
|
|
622
679
|
parentClassName,
|
|
623
680
|
context,
|
|
@@ -629,7 +686,6 @@ const validateStatement = ({
|
|
|
629
686
|
}
|
|
630
687
|
};
|
|
631
688
|
const validateIfStatement = ({
|
|
632
|
-
node,
|
|
633
689
|
statement,
|
|
634
690
|
parentClassName,
|
|
635
691
|
context,
|
|
@@ -637,7 +693,6 @@ const validateIfStatement = ({
|
|
|
637
693
|
option
|
|
638
694
|
}) => {
|
|
639
695
|
traverseStatements({
|
|
640
|
-
node,
|
|
641
696
|
context,
|
|
642
697
|
parentClassName,
|
|
643
698
|
statement: statement.consequent,
|
|
@@ -646,7 +701,6 @@ const validateIfStatement = ({
|
|
|
646
701
|
});
|
|
647
702
|
};
|
|
648
703
|
const validateSwitchStatement = ({
|
|
649
|
-
node,
|
|
650
704
|
statement,
|
|
651
705
|
parentClassName,
|
|
652
706
|
context,
|
|
@@ -656,7 +710,6 @@ const validateSwitchStatement = ({
|
|
|
656
710
|
for (const caseStatement of statement.cases) {
|
|
657
711
|
for (const _consequent of caseStatement.consequent) {
|
|
658
712
|
traverseStatements({
|
|
659
|
-
node,
|
|
660
713
|
context,
|
|
661
714
|
parentClassName,
|
|
662
715
|
statement: _consequent,
|
|
@@ -667,7 +720,6 @@ const validateSwitchStatement = ({
|
|
|
667
720
|
}
|
|
668
721
|
};
|
|
669
722
|
const validateConstructId$2 = ({
|
|
670
|
-
node,
|
|
671
723
|
context,
|
|
672
724
|
expression,
|
|
673
725
|
parentClassName,
|
|
@@ -685,8 +737,8 @@ const validateConstructId$2 = ({
|
|
|
685
737
|
if (!isConstructType(type)) return;
|
|
686
738
|
if (option.disallowContainingParentName && formattedConstructId.includes(formattedParentClassName)) {
|
|
687
739
|
context.report({
|
|
688
|
-
node,
|
|
689
|
-
messageId: "
|
|
740
|
+
node: secondArg,
|
|
741
|
+
messageId: "invalidConstructId",
|
|
690
742
|
data: {
|
|
691
743
|
constructId: secondArg.value,
|
|
692
744
|
parentConstructName: parentClassName
|
|
@@ -696,8 +748,8 @@ const validateConstructId$2 = ({
|
|
|
696
748
|
}
|
|
697
749
|
if (formattedParentClassName === formattedConstructId) {
|
|
698
750
|
context.report({
|
|
699
|
-
node,
|
|
700
|
-
messageId: "
|
|
751
|
+
node: secondArg,
|
|
752
|
+
messageId: "invalidConstructId",
|
|
701
753
|
data: {
|
|
702
754
|
constructId: secondArg.value,
|
|
703
755
|
parentConstructName: parentClassName
|
|
@@ -706,87 +758,6 @@ const validateConstructId$2 = ({
|
|
|
706
758
|
}
|
|
707
759
|
};
|
|
708
760
|
|
|
709
|
-
const noPublicClassFields = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
710
|
-
meta: {
|
|
711
|
-
type: "problem",
|
|
712
|
-
docs: {
|
|
713
|
-
description: "Disallow class types in public class fields"
|
|
714
|
-
},
|
|
715
|
-
messages: {
|
|
716
|
-
noPublicClassFields: "Public field '{{ propertyName }}' should not use class type '{{ typeName }}'. Consider using an interface or type alias instead."
|
|
717
|
-
},
|
|
718
|
-
schema: []
|
|
719
|
-
},
|
|
720
|
-
defaultOptions: [],
|
|
721
|
-
create(context) {
|
|
722
|
-
const parserServices = utils.ESLintUtils.getParserServices(context);
|
|
723
|
-
return {
|
|
724
|
-
ClassDeclaration(node) {
|
|
725
|
-
const type = parserServices.getTypeAtLocation(node);
|
|
726
|
-
if (!isConstructOrStackType(type)) return;
|
|
727
|
-
validateClassMember(node, context, parserServices);
|
|
728
|
-
const constructor = node.body.body.find(
|
|
729
|
-
(member) => member.type === utils.AST_NODE_TYPES.MethodDefinition && member.kind === "constructor"
|
|
730
|
-
);
|
|
731
|
-
if (!constructor || constructor.value.type !== utils.AST_NODE_TYPES.FunctionExpression) {
|
|
732
|
-
return;
|
|
733
|
-
}
|
|
734
|
-
validateConstructorParameterProperty(
|
|
735
|
-
constructor,
|
|
736
|
-
context,
|
|
737
|
-
parserServices
|
|
738
|
-
);
|
|
739
|
-
}
|
|
740
|
-
};
|
|
741
|
-
}
|
|
742
|
-
});
|
|
743
|
-
const validateClassMember = (node, context, parserServices) => {
|
|
744
|
-
for (const member of node.body.body) {
|
|
745
|
-
if (member.type !== utils.AST_NODE_TYPES.PropertyDefinition || member.key.type !== utils.AST_NODE_TYPES.Identifier) {
|
|
746
|
-
continue;
|
|
747
|
-
}
|
|
748
|
-
if (["private", "protected"].includes(member.accessibility ?? "")) {
|
|
749
|
-
continue;
|
|
750
|
-
}
|
|
751
|
-
if (!member.typeAnnotation) continue;
|
|
752
|
-
const type = parserServices.getTypeAtLocation(member);
|
|
753
|
-
if (!type.symbol) continue;
|
|
754
|
-
const isClass = type.symbol.flags === SYMBOL_FLAGS.CLASS;
|
|
755
|
-
if (!isClass) continue;
|
|
756
|
-
context.report({
|
|
757
|
-
node: member,
|
|
758
|
-
messageId: "noPublicClassFields",
|
|
759
|
-
data: {
|
|
760
|
-
propertyName: member.key.name,
|
|
761
|
-
typeName: type.symbol.name
|
|
762
|
-
}
|
|
763
|
-
});
|
|
764
|
-
}
|
|
765
|
-
};
|
|
766
|
-
const validateConstructorParameterProperty = (constructor, context, parserServices) => {
|
|
767
|
-
for (const param of constructor.value.params) {
|
|
768
|
-
if (param.type !== utils.AST_NODE_TYPES.TSParameterProperty || param.parameter.type !== utils.AST_NODE_TYPES.Identifier) {
|
|
769
|
-
continue;
|
|
770
|
-
}
|
|
771
|
-
if (["private", "protected"].includes(param.accessibility ?? "")) {
|
|
772
|
-
continue;
|
|
773
|
-
}
|
|
774
|
-
if (!param.parameter.typeAnnotation) continue;
|
|
775
|
-
const type = parserServices.getTypeAtLocation(param);
|
|
776
|
-
if (!type.symbol) continue;
|
|
777
|
-
const isClass = type.symbol.flags === SYMBOL_FLAGS.CLASS;
|
|
778
|
-
if (!isClass) continue;
|
|
779
|
-
context.report({
|
|
780
|
-
node: param,
|
|
781
|
-
messageId: "noPublicClassFields",
|
|
782
|
-
data: {
|
|
783
|
-
propertyName: param.parameter.name,
|
|
784
|
-
typeName: type.symbol.name
|
|
785
|
-
}
|
|
786
|
-
});
|
|
787
|
-
}
|
|
788
|
-
};
|
|
789
|
-
|
|
790
761
|
const noVariableConstructId = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
791
762
|
meta: {
|
|
792
763
|
type: "problem",
|
|
@@ -794,7 +765,7 @@ const noVariableConstructId = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
|
794
765
|
description: `Enforce using literal strings for Construct ID.`
|
|
795
766
|
},
|
|
796
767
|
messages: {
|
|
797
|
-
|
|
768
|
+
invalidConstructId: "Shouldn't use a parameter as a Construct ID."
|
|
798
769
|
},
|
|
799
770
|
schema: []
|
|
800
771
|
},
|
|
@@ -822,8 +793,8 @@ const validateConstructId$1 = (node, context) => {
|
|
|
822
793
|
return;
|
|
823
794
|
}
|
|
824
795
|
context.report({
|
|
825
|
-
node,
|
|
826
|
-
messageId: "
|
|
796
|
+
node: secondArg,
|
|
797
|
+
messageId: "invalidConstructId"
|
|
827
798
|
});
|
|
828
799
|
};
|
|
829
800
|
const isInsideLoop = (node) => {
|
|
@@ -859,7 +830,7 @@ const pascalCaseConstructId = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
|
859
830
|
description: "Enforce PascalCase for Construct ID."
|
|
860
831
|
},
|
|
861
832
|
messages: {
|
|
862
|
-
|
|
833
|
+
invalidConstructId: "Construct ID must be PascalCase."
|
|
863
834
|
},
|
|
864
835
|
schema: [],
|
|
865
836
|
fixable: "code"
|
|
@@ -892,8 +863,8 @@ const validateConstructId = (node, context) => {
|
|
|
892
863
|
const quote = secondArg.raw?.startsWith('"') ? QUOTE_TYPE.DOUBLE : QUOTE_TYPE.SINGLE;
|
|
893
864
|
if (isPascalCase(secondArg.value)) return;
|
|
894
865
|
context.report({
|
|
895
|
-
node,
|
|
896
|
-
messageId: "
|
|
866
|
+
node: secondArg,
|
|
867
|
+
messageId: "invalidConstructId",
|
|
897
868
|
fix: (fixer) => {
|
|
898
869
|
const pascalCaseValue = toPascalCase(secondArg.value);
|
|
899
870
|
return fixer.replaceText(secondArg, `${quote}${pascalCaseValue}${quote}`);
|
|
@@ -1020,7 +991,7 @@ const requirePassingThis = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
|
1020
991
|
description: "Require passing `this` in a constructor."
|
|
1021
992
|
},
|
|
1022
993
|
messages: {
|
|
1023
|
-
|
|
994
|
+
missingPassingThis: "Require passing `this` in a constructor."
|
|
1024
995
|
},
|
|
1025
996
|
schema: [
|
|
1026
997
|
{
|
|
@@ -1056,8 +1027,8 @@ const requirePassingThis = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
|
1056
1027
|
if (constructorPropertyNames[0] !== "scope") return;
|
|
1057
1028
|
if (!options.allowNonThisAndDisallowScope) {
|
|
1058
1029
|
context.report({
|
|
1059
|
-
node,
|
|
1060
|
-
messageId: "
|
|
1030
|
+
node: argument,
|
|
1031
|
+
messageId: "missingPassingThis",
|
|
1061
1032
|
fix: (fixer) => {
|
|
1062
1033
|
return fixer.replaceText(argument, "this");
|
|
1063
1034
|
}
|
|
@@ -1066,8 +1037,8 @@ const requirePassingThis = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
|
1066
1037
|
}
|
|
1067
1038
|
if (argument.type === utils.AST_NODE_TYPES.Identifier && argument.name === "scope") {
|
|
1068
1039
|
context.report({
|
|
1069
|
-
node,
|
|
1070
|
-
messageId: "
|
|
1040
|
+
node: argument,
|
|
1041
|
+
messageId: "missingPassingThis",
|
|
1071
1042
|
fix: (fixer) => {
|
|
1072
1043
|
return fixer.replaceText(argument, "this");
|
|
1073
1044
|
}
|
|
@@ -1121,20 +1092,20 @@ const requirePropsDefaultDoc = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
|
1121
1092
|
});
|
|
1122
1093
|
|
|
1123
1094
|
const rules = {
|
|
1124
|
-
"
|
|
1095
|
+
"construct-constructor-property": constructConstructorProperty,
|
|
1096
|
+
"no-construct-in-interface": noConstructInInterface,
|
|
1097
|
+
"no-construct-in-public-property-of-construct": noConstructInPublicPropertyOfConstruct,
|
|
1125
1098
|
"no-construct-stack-suffix": noConstructStackSuffix,
|
|
1099
|
+
"no-import-private": noImportPrivate,
|
|
1100
|
+
"no-mutable-property-of-props-interface": noMutablePropertyOfPropsInterface,
|
|
1101
|
+
"no-mutable-public-property-of-construct": noMutablePublicPropertyOfConstruct,
|
|
1126
1102
|
"no-parent-name-construct-id-match": noParentNameConstructIdMatch,
|
|
1127
|
-
"no-public-class-fields": noPublicClassFields,
|
|
1128
|
-
"pascal-case-construct-id": pascalCaseConstructId,
|
|
1129
|
-
"require-passing-this": requirePassingThis,
|
|
1130
1103
|
"no-variable-construct-id": noVariableConstructId,
|
|
1131
|
-
"
|
|
1132
|
-
"no-mutable-props-interface": noMutablePropsInterface,
|
|
1133
|
-
"construct-constructor-property": constructConstructorProperty,
|
|
1134
|
-
"require-jsdoc": requireJSDoc,
|
|
1135
|
-
"require-props-default-doc": requirePropsDefaultDoc,
|
|
1104
|
+
"pascal-case-construct-id": pascalCaseConstructId,
|
|
1136
1105
|
"props-name-convention": propsNameConvention,
|
|
1137
|
-
"
|
|
1106
|
+
"require-jsdoc": requireJSDoc,
|
|
1107
|
+
"require-passing-this": requirePassingThis,
|
|
1108
|
+
"require-props-default-doc": requirePropsDefaultDoc
|
|
1138
1109
|
};
|
|
1139
1110
|
const cdkPlugin = {
|
|
1140
1111
|
meta: { name, version },
|
|
@@ -1155,38 +1126,38 @@ const createFlatConfig = (rules2) => {
|
|
|
1155
1126
|
};
|
|
1156
1127
|
};
|
|
1157
1128
|
const recommended = createFlatConfig({
|
|
1158
|
-
"cdk/
|
|
1129
|
+
"cdk/construct-constructor-property": "error",
|
|
1130
|
+
"cdk/no-construct-in-interface": "error",
|
|
1131
|
+
"cdk/no-construct-in-public-property-of-construct": "error",
|
|
1159
1132
|
"cdk/no-construct-stack-suffix": "error",
|
|
1133
|
+
"cdk/no-mutable-property-of-props-interface": "warn",
|
|
1134
|
+
"cdk/no-mutable-public-property-of-construct": "warn",
|
|
1160
1135
|
"cdk/no-parent-name-construct-id-match": [
|
|
1161
1136
|
"error",
|
|
1162
1137
|
{ disallowContainingParentName: false }
|
|
1163
1138
|
],
|
|
1164
|
-
"cdk/no-public-class-fields": "error",
|
|
1165
|
-
"cdk/pascal-case-construct-id": "error",
|
|
1166
|
-
"cdk/require-passing-this": ["error", { allowNonThisAndDisallowScope: true }],
|
|
1167
1139
|
"cdk/no-variable-construct-id": "error",
|
|
1168
|
-
"cdk/
|
|
1169
|
-
"cdk/
|
|
1170
|
-
"cdk/construct-constructor-property": "error"
|
|
1140
|
+
"cdk/pascal-case-construct-id": "error",
|
|
1141
|
+
"cdk/require-passing-this": ["error", { allowNonThisAndDisallowScope: true }]
|
|
1171
1142
|
});
|
|
1172
1143
|
const strict = createFlatConfig({
|
|
1173
|
-
"cdk/
|
|
1144
|
+
"cdk/construct-constructor-property": "error",
|
|
1145
|
+
"cdk/no-construct-in-interface": "error",
|
|
1146
|
+
"cdk/no-construct-in-public-property-of-construct": "error",
|
|
1174
1147
|
"cdk/no-construct-stack-suffix": "error",
|
|
1148
|
+
"cdk/no-import-private": "error",
|
|
1149
|
+
"cdk/no-mutable-property-of-props-interface": "error",
|
|
1150
|
+
"cdk/no-mutable-public-property-of-construct": "error",
|
|
1175
1151
|
"cdk/no-parent-name-construct-id-match": [
|
|
1176
1152
|
"error",
|
|
1177
1153
|
{ disallowContainingParentName: true }
|
|
1178
1154
|
],
|
|
1179
|
-
"cdk/no-public-class-fields": "error",
|
|
1180
|
-
"cdk/pascal-case-construct-id": "error",
|
|
1181
|
-
"cdk/require-passing-this": "error",
|
|
1182
1155
|
"cdk/no-variable-construct-id": "error",
|
|
1183
|
-
"cdk/
|
|
1184
|
-
"cdk/no-mutable-props-interface": "error",
|
|
1185
|
-
"cdk/construct-constructor-property": "error",
|
|
1186
|
-
"cdk/require-jsdoc": "error",
|
|
1187
|
-
"cdk/require-props-default-doc": "error",
|
|
1156
|
+
"cdk/pascal-case-construct-id": "error",
|
|
1188
1157
|
"cdk/props-name-convention": "error",
|
|
1189
|
-
"cdk/
|
|
1158
|
+
"cdk/require-jsdoc": "error",
|
|
1159
|
+
"cdk/require-passing-this": "error",
|
|
1160
|
+
"cdk/require-props-default-doc": "error"
|
|
1190
1161
|
});
|
|
1191
1162
|
const configs = {
|
|
1192
1163
|
recommended,
|