eslint-cdk-plugin 2.2.0 → 3.0.2
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 -169
- package/dist/index.d.ts +39 -39
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +149 -169
- 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 -7
- package/src/rules/no-construct-in-public-property-of-construct.ts +155 -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
|
@@ -26,7 +26,7 @@ function _interopNamespaceDefault(e) {
|
|
|
26
26
|
var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
|
|
27
27
|
|
|
28
28
|
var name = "eslint-cdk-plugin";
|
|
29
|
-
var version = "
|
|
29
|
+
var version = "3.0.1";
|
|
30
30
|
|
|
31
31
|
const isConstructOrStackType = (type, ignoredClasses = ["App", "Stage"]) => {
|
|
32
32
|
if (ignoredClasses.includes(type.symbol?.name ?? "")) return false;
|
|
@@ -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,7 +107,7 @@ 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;
|
|
@@ -122,14 +122,14 @@ const SYNTAX_KIND = {
|
|
|
122
122
|
CONSTRUCTOR: 176
|
|
123
123
|
};
|
|
124
124
|
|
|
125
|
-
const
|
|
125
|
+
const noConstructInInterface = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
126
126
|
meta: {
|
|
127
127
|
type: "problem",
|
|
128
128
|
docs: {
|
|
129
|
-
description: "Disallow
|
|
129
|
+
description: "Disallow CDK Construct types in interface properties"
|
|
130
130
|
},
|
|
131
131
|
messages: {
|
|
132
|
-
|
|
132
|
+
invalidInterfaceProperty: "Interface property '{{ propertyName }}' should not use CDK Construct type '{{ typeName }}'. Consider using an interface or type alias instead."
|
|
133
133
|
},
|
|
134
134
|
schema: []
|
|
135
135
|
},
|
|
@@ -143,12 +143,12 @@ const noClassInInterface = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
|
143
143
|
continue;
|
|
144
144
|
}
|
|
145
145
|
const type = parserServices.getTypeAtLocation(property);
|
|
146
|
-
if (!type
|
|
146
|
+
if (!isConstructOrStackType(type)) continue;
|
|
147
147
|
const isClass = type.symbol.flags === SYMBOL_FLAGS.CLASS;
|
|
148
148
|
if (!isClass) continue;
|
|
149
149
|
context.report({
|
|
150
150
|
node: property,
|
|
151
|
-
messageId: "
|
|
151
|
+
messageId: "invalidInterfaceProperty",
|
|
152
152
|
data: {
|
|
153
153
|
propertyName: property.key.name,
|
|
154
154
|
typeName: type.symbol.name
|
|
@@ -160,6 +160,87 @@ const noClassInInterface = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
|
160
160
|
}
|
|
161
161
|
});
|
|
162
162
|
|
|
163
|
+
const noConstructInPublicPropertyOfConstruct = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
164
|
+
meta: {
|
|
165
|
+
type: "problem",
|
|
166
|
+
docs: {
|
|
167
|
+
description: "Disallow Construct types in public property of Construct"
|
|
168
|
+
},
|
|
169
|
+
messages: {
|
|
170
|
+
invalidPublicPropertyOfConstruct: "Public property '{{ propertyName }}' of Construct should not use Construct type '{{ typeName }}'. Consider using an interface or type alias instead."
|
|
171
|
+
},
|
|
172
|
+
schema: []
|
|
173
|
+
},
|
|
174
|
+
defaultOptions: [],
|
|
175
|
+
create(context) {
|
|
176
|
+
const parserServices = utils.ESLintUtils.getParserServices(context);
|
|
177
|
+
return {
|
|
178
|
+
ClassDeclaration(node) {
|
|
179
|
+
const type = parserServices.getTypeAtLocation(node);
|
|
180
|
+
if (!isConstructOrStackType(type)) return;
|
|
181
|
+
validatePublicPropertyOfConstruct(node, context, parserServices);
|
|
182
|
+
const constructor = node.body.body.find(
|
|
183
|
+
(member) => member.type === utils.AST_NODE_TYPES.MethodDefinition && member.kind === "constructor"
|
|
184
|
+
);
|
|
185
|
+
if (!constructor || constructor.value.type !== utils.AST_NODE_TYPES.FunctionExpression) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
validateConstructorParameterProperty(
|
|
189
|
+
constructor,
|
|
190
|
+
context,
|
|
191
|
+
parserServices
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
const validatePublicPropertyOfConstruct = (node, context, parserServices) => {
|
|
198
|
+
for (const property of node.body.body) {
|
|
199
|
+
if (property.type !== utils.AST_NODE_TYPES.PropertyDefinition || property.key.type !== utils.AST_NODE_TYPES.Identifier) {
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
if (["private", "protected"].includes(property.accessibility ?? "")) {
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
if (!property.typeAnnotation) continue;
|
|
206
|
+
const type = parserServices.getTypeAtLocation(property);
|
|
207
|
+
if (!isConstructOrStackType(type)) continue;
|
|
208
|
+
const isClass = type.symbol.flags === SYMBOL_FLAGS.CLASS;
|
|
209
|
+
if (!isClass) continue;
|
|
210
|
+
context.report({
|
|
211
|
+
node: property,
|
|
212
|
+
messageId: "invalidPublicPropertyOfConstruct",
|
|
213
|
+
data: {
|
|
214
|
+
propertyName: property.key.name,
|
|
215
|
+
typeName: type.symbol.name
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
const validateConstructorParameterProperty = (constructor, context, parserServices) => {
|
|
221
|
+
for (const param of constructor.value.params) {
|
|
222
|
+
if (param.type !== utils.AST_NODE_TYPES.TSParameterProperty || param.parameter.type !== utils.AST_NODE_TYPES.Identifier) {
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
if (["private", "protected"].includes(param.accessibility ?? "")) {
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
if (!param.parameter.typeAnnotation) continue;
|
|
229
|
+
const type = parserServices.getTypeAtLocation(param);
|
|
230
|
+
if (!isConstructOrStackType(type)) continue;
|
|
231
|
+
const isClass = type.symbol.flags === SYMBOL_FLAGS.CLASS;
|
|
232
|
+
if (!isClass) continue;
|
|
233
|
+
context.report({
|
|
234
|
+
node: param,
|
|
235
|
+
messageId: "invalidPublicPropertyOfConstruct",
|
|
236
|
+
data: {
|
|
237
|
+
propertyName: param.parameter.name,
|
|
238
|
+
typeName: type.symbol.name
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
|
|
163
244
|
const toPascalCase = (str) => {
|
|
164
245
|
return str.split(/[-_\s]/).map((word) => {
|
|
165
246
|
return word.replace(/([A-Z])/g, " $1").split(/\s+/).map(
|
|
@@ -197,7 +278,7 @@ const noConstructStackSuffix = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
|
197
278
|
description: "Effort to avoid using 'Construct' and 'Stack' suffix in construct id."
|
|
198
279
|
},
|
|
199
280
|
messages: {
|
|
200
|
-
|
|
281
|
+
invalidConstructId: "{{ classType }} ID '{{ id }}' should not include {{ suffix }} suffix."
|
|
201
282
|
},
|
|
202
283
|
schema: [
|
|
203
284
|
{
|
|
@@ -248,8 +329,8 @@ const validateConstructId$3 = (node, context, options) => {
|
|
|
248
329
|
const disallowedSuffixes = options.disallowedSuffixes;
|
|
249
330
|
if (disallowedSuffixes.includes(SUFFIX_TYPE.CONSTRUCT) && formattedConstructId.endsWith(SUFFIX_TYPE.CONSTRUCT)) {
|
|
250
331
|
context.report({
|
|
251
|
-
node,
|
|
252
|
-
messageId: "
|
|
332
|
+
node: secondArg,
|
|
333
|
+
messageId: "invalidConstructId",
|
|
253
334
|
data: {
|
|
254
335
|
classType: "Construct",
|
|
255
336
|
id: secondArg.value,
|
|
@@ -258,8 +339,8 @@ const validateConstructId$3 = (node, context, options) => {
|
|
|
258
339
|
});
|
|
259
340
|
} else if (disallowedSuffixes.includes(SUFFIX_TYPE.STACK) && formattedConstructId.endsWith(SUFFIX_TYPE.STACK)) {
|
|
260
341
|
context.report({
|
|
261
|
-
node,
|
|
262
|
-
messageId: "
|
|
342
|
+
node: secondArg,
|
|
343
|
+
messageId: "invalidConstructId",
|
|
263
344
|
data: {
|
|
264
345
|
classType: "Stack",
|
|
265
346
|
id: secondArg.value,
|
|
@@ -276,7 +357,7 @@ const noImportPrivate = {
|
|
|
276
357
|
description: "Cannot import modules from private dir at different levels of the hierarchy."
|
|
277
358
|
},
|
|
278
359
|
messages: {
|
|
279
|
-
|
|
360
|
+
invalidImportPath: "Cannot import modules from private dir at different levels of the hierarchy."
|
|
280
361
|
},
|
|
281
362
|
schema: []
|
|
282
363
|
},
|
|
@@ -295,7 +376,7 @@ const noImportPrivate = {
|
|
|
295
376
|
if (currentDirSegments.length !== importDirSegments.length || currentDirSegments.some(
|
|
296
377
|
(segment, index) => segment !== importDirSegments[index]
|
|
297
378
|
)) {
|
|
298
|
-
context.report({ node, messageId: "
|
|
379
|
+
context.report({ node, messageId: "invalidImportPath" });
|
|
299
380
|
}
|
|
300
381
|
}
|
|
301
382
|
};
|
|
@@ -305,15 +386,15 @@ const getDirSegments = (dirPath) => {
|
|
|
305
386
|
return dirPath.split(path__namespace.sep).filter((segment) => segment !== "");
|
|
306
387
|
};
|
|
307
388
|
|
|
308
|
-
const
|
|
389
|
+
const noMutablePropertyOfPropsInterface = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
309
390
|
meta: {
|
|
310
391
|
type: "problem",
|
|
311
392
|
docs: {
|
|
312
|
-
description: "Disallow mutable properties
|
|
393
|
+
description: "Disallow mutable properties of Construct Props (interface)"
|
|
313
394
|
},
|
|
314
395
|
fixable: "code",
|
|
315
396
|
messages: {
|
|
316
|
-
|
|
397
|
+
invalidPropertyOfPropsInterface: "Property '{{ propertyName }}' of Construct Props should be readonly."
|
|
317
398
|
},
|
|
318
399
|
schema: []
|
|
319
400
|
},
|
|
@@ -330,7 +411,7 @@ const noMutablePropsInterface = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
|
330
411
|
if (property.readonly) continue;
|
|
331
412
|
context.report({
|
|
332
413
|
node: property,
|
|
333
|
-
messageId: "
|
|
414
|
+
messageId: "invalidPropertyOfPropsInterface",
|
|
334
415
|
data: {
|
|
335
416
|
propertyName: property.key.name
|
|
336
417
|
},
|
|
@@ -345,15 +426,15 @@ const noMutablePropsInterface = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
|
345
426
|
}
|
|
346
427
|
});
|
|
347
428
|
|
|
348
|
-
const
|
|
429
|
+
const noMutablePublicPropertyOfConstruct = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
349
430
|
meta: {
|
|
350
431
|
type: "problem",
|
|
351
432
|
docs: {
|
|
352
|
-
description: "Disallow mutable public
|
|
433
|
+
description: "Disallow mutable public properties of Construct"
|
|
353
434
|
},
|
|
354
435
|
fixable: "code",
|
|
355
436
|
messages: {
|
|
356
|
-
|
|
437
|
+
invalidPublicPropertyOfConstruct: "Public property '{{ propertyName }}' should be readonly. Consider adding the 'readonly' modifier."
|
|
357
438
|
},
|
|
358
439
|
schema: []
|
|
359
440
|
},
|
|
@@ -375,7 +456,7 @@ const noMutablePublicFields = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
|
375
456
|
if (member.readonly) continue;
|
|
376
457
|
context.report({
|
|
377
458
|
node: member,
|
|
378
|
-
messageId: "
|
|
459
|
+
messageId: "invalidPublicPropertyOfConstruct",
|
|
379
460
|
data: {
|
|
380
461
|
propertyName: member.key.name
|
|
381
462
|
},
|
|
@@ -404,7 +485,7 @@ const noParentNameConstructIdMatch = utils.ESLintUtils.RuleCreator.withoutDocs(
|
|
|
404
485
|
description: "Enforce that construct IDs does not match the parent construct name."
|
|
405
486
|
},
|
|
406
487
|
messages: {
|
|
407
|
-
|
|
488
|
+
invalidConstructId: "Construct ID '{{ constructId }}' should not match parent construct name '{{ parentConstructName }}'. Use a more specific identifier."
|
|
408
489
|
},
|
|
409
490
|
schema: [
|
|
410
491
|
{
|
|
@@ -442,7 +523,6 @@ const noParentNameConstructIdMatch = utils.ESLintUtils.RuleCreator.withoutDocs(
|
|
|
442
523
|
continue;
|
|
443
524
|
}
|
|
444
525
|
validateConstructorBody({
|
|
445
|
-
node,
|
|
446
526
|
expression: body.value,
|
|
447
527
|
parentClassName,
|
|
448
528
|
context,
|
|
@@ -456,7 +536,6 @@ const noParentNameConstructIdMatch = utils.ESLintUtils.RuleCreator.withoutDocs(
|
|
|
456
536
|
}
|
|
457
537
|
);
|
|
458
538
|
const validateConstructorBody = ({
|
|
459
|
-
node,
|
|
460
539
|
expression,
|
|
461
540
|
parentClassName,
|
|
462
541
|
context,
|
|
@@ -469,7 +548,6 @@ const validateConstructorBody = ({
|
|
|
469
548
|
const newExpression = statement.declarations[0].init;
|
|
470
549
|
if (newExpression?.type !== utils.AST_NODE_TYPES.NewExpression) continue;
|
|
471
550
|
validateConstructId$2({
|
|
472
|
-
node,
|
|
473
551
|
context,
|
|
474
552
|
expression: newExpression,
|
|
475
553
|
parentClassName,
|
|
@@ -481,7 +559,6 @@ const validateConstructorBody = ({
|
|
|
481
559
|
case utils.AST_NODE_TYPES.ExpressionStatement: {
|
|
482
560
|
if (statement.expression?.type !== utils.AST_NODE_TYPES.NewExpression) break;
|
|
483
561
|
validateStatement({
|
|
484
|
-
node,
|
|
485
562
|
statement,
|
|
486
563
|
parentClassName,
|
|
487
564
|
context,
|
|
@@ -492,7 +569,6 @@ const validateConstructorBody = ({
|
|
|
492
569
|
}
|
|
493
570
|
case utils.AST_NODE_TYPES.IfStatement: {
|
|
494
571
|
traverseStatements({
|
|
495
|
-
node,
|
|
496
572
|
context,
|
|
497
573
|
parentClassName,
|
|
498
574
|
statement: statement.consequent,
|
|
@@ -505,7 +581,6 @@ const validateConstructorBody = ({
|
|
|
505
581
|
for (const switchCase of statement.cases) {
|
|
506
582
|
for (const statement2 of switchCase.consequent) {
|
|
507
583
|
traverseStatements({
|
|
508
|
-
node,
|
|
509
584
|
context,
|
|
510
585
|
parentClassName,
|
|
511
586
|
statement: statement2,
|
|
@@ -520,7 +595,6 @@ const validateConstructorBody = ({
|
|
|
520
595
|
}
|
|
521
596
|
};
|
|
522
597
|
const traverseStatements = ({
|
|
523
|
-
node,
|
|
524
598
|
statement,
|
|
525
599
|
parentClassName,
|
|
526
600
|
context,
|
|
@@ -531,7 +605,6 @@ const traverseStatements = ({
|
|
|
531
605
|
case utils.AST_NODE_TYPES.BlockStatement: {
|
|
532
606
|
for (const body of statement.body) {
|
|
533
607
|
validateStatement({
|
|
534
|
-
node,
|
|
535
608
|
statement: body,
|
|
536
609
|
parentClassName,
|
|
537
610
|
context,
|
|
@@ -545,7 +618,6 @@ const traverseStatements = ({
|
|
|
545
618
|
const newExpression = statement.expression;
|
|
546
619
|
if (newExpression?.type !== utils.AST_NODE_TYPES.NewExpression) break;
|
|
547
620
|
validateStatement({
|
|
548
|
-
node,
|
|
549
621
|
statement,
|
|
550
622
|
parentClassName,
|
|
551
623
|
context,
|
|
@@ -558,7 +630,6 @@ const traverseStatements = ({
|
|
|
558
630
|
const newExpression = statement.declarations[0].init;
|
|
559
631
|
if (newExpression?.type !== utils.AST_NODE_TYPES.NewExpression) break;
|
|
560
632
|
validateConstructId$2({
|
|
561
|
-
node,
|
|
562
633
|
context,
|
|
563
634
|
expression: newExpression,
|
|
564
635
|
parentClassName,
|
|
@@ -570,7 +641,6 @@ const traverseStatements = ({
|
|
|
570
641
|
}
|
|
571
642
|
};
|
|
572
643
|
const validateStatement = ({
|
|
573
|
-
node,
|
|
574
644
|
statement,
|
|
575
645
|
parentClassName,
|
|
576
646
|
context,
|
|
@@ -582,7 +652,6 @@ const validateStatement = ({
|
|
|
582
652
|
const newExpression = statement.declarations[0].init;
|
|
583
653
|
if (newExpression?.type !== utils.AST_NODE_TYPES.NewExpression) break;
|
|
584
654
|
validateConstructId$2({
|
|
585
|
-
node,
|
|
586
655
|
context,
|
|
587
656
|
expression: newExpression,
|
|
588
657
|
parentClassName,
|
|
@@ -595,7 +664,6 @@ const validateStatement = ({
|
|
|
595
664
|
const newExpression = statement.expression;
|
|
596
665
|
if (newExpression?.type !== utils.AST_NODE_TYPES.NewExpression) break;
|
|
597
666
|
validateConstructId$2({
|
|
598
|
-
node,
|
|
599
667
|
context,
|
|
600
668
|
expression: newExpression,
|
|
601
669
|
parentClassName,
|
|
@@ -606,7 +674,6 @@ const validateStatement = ({
|
|
|
606
674
|
}
|
|
607
675
|
case utils.AST_NODE_TYPES.IfStatement: {
|
|
608
676
|
validateIfStatement({
|
|
609
|
-
node,
|
|
610
677
|
statement,
|
|
611
678
|
parentClassName,
|
|
612
679
|
context,
|
|
@@ -617,7 +684,6 @@ const validateStatement = ({
|
|
|
617
684
|
}
|
|
618
685
|
case utils.AST_NODE_TYPES.SwitchStatement: {
|
|
619
686
|
validateSwitchStatement({
|
|
620
|
-
node,
|
|
621
687
|
statement,
|
|
622
688
|
parentClassName,
|
|
623
689
|
context,
|
|
@@ -629,7 +695,6 @@ const validateStatement = ({
|
|
|
629
695
|
}
|
|
630
696
|
};
|
|
631
697
|
const validateIfStatement = ({
|
|
632
|
-
node,
|
|
633
698
|
statement,
|
|
634
699
|
parentClassName,
|
|
635
700
|
context,
|
|
@@ -637,7 +702,6 @@ const validateIfStatement = ({
|
|
|
637
702
|
option
|
|
638
703
|
}) => {
|
|
639
704
|
traverseStatements({
|
|
640
|
-
node,
|
|
641
705
|
context,
|
|
642
706
|
parentClassName,
|
|
643
707
|
statement: statement.consequent,
|
|
@@ -646,7 +710,6 @@ const validateIfStatement = ({
|
|
|
646
710
|
});
|
|
647
711
|
};
|
|
648
712
|
const validateSwitchStatement = ({
|
|
649
|
-
node,
|
|
650
713
|
statement,
|
|
651
714
|
parentClassName,
|
|
652
715
|
context,
|
|
@@ -656,7 +719,6 @@ const validateSwitchStatement = ({
|
|
|
656
719
|
for (const caseStatement of statement.cases) {
|
|
657
720
|
for (const _consequent of caseStatement.consequent) {
|
|
658
721
|
traverseStatements({
|
|
659
|
-
node,
|
|
660
722
|
context,
|
|
661
723
|
parentClassName,
|
|
662
724
|
statement: _consequent,
|
|
@@ -667,7 +729,6 @@ const validateSwitchStatement = ({
|
|
|
667
729
|
}
|
|
668
730
|
};
|
|
669
731
|
const validateConstructId$2 = ({
|
|
670
|
-
node,
|
|
671
732
|
context,
|
|
672
733
|
expression,
|
|
673
734
|
parentClassName,
|
|
@@ -685,8 +746,8 @@ const validateConstructId$2 = ({
|
|
|
685
746
|
if (!isConstructType(type)) return;
|
|
686
747
|
if (option.disallowContainingParentName && formattedConstructId.includes(formattedParentClassName)) {
|
|
687
748
|
context.report({
|
|
688
|
-
node,
|
|
689
|
-
messageId: "
|
|
749
|
+
node: secondArg,
|
|
750
|
+
messageId: "invalidConstructId",
|
|
690
751
|
data: {
|
|
691
752
|
constructId: secondArg.value,
|
|
692
753
|
parentConstructName: parentClassName
|
|
@@ -696,8 +757,8 @@ const validateConstructId$2 = ({
|
|
|
696
757
|
}
|
|
697
758
|
if (formattedParentClassName === formattedConstructId) {
|
|
698
759
|
context.report({
|
|
699
|
-
node,
|
|
700
|
-
messageId: "
|
|
760
|
+
node: secondArg,
|
|
761
|
+
messageId: "invalidConstructId",
|
|
701
762
|
data: {
|
|
702
763
|
constructId: secondArg.value,
|
|
703
764
|
parentConstructName: parentClassName
|
|
@@ -706,87 +767,6 @@ const validateConstructId$2 = ({
|
|
|
706
767
|
}
|
|
707
768
|
};
|
|
708
769
|
|
|
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
770
|
const noVariableConstructId = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
791
771
|
meta: {
|
|
792
772
|
type: "problem",
|
|
@@ -794,7 +774,7 @@ const noVariableConstructId = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
|
794
774
|
description: `Enforce using literal strings for Construct ID.`
|
|
795
775
|
},
|
|
796
776
|
messages: {
|
|
797
|
-
|
|
777
|
+
invalidConstructId: "Shouldn't use a parameter as a Construct ID."
|
|
798
778
|
},
|
|
799
779
|
schema: []
|
|
800
780
|
},
|
|
@@ -822,8 +802,8 @@ const validateConstructId$1 = (node, context) => {
|
|
|
822
802
|
return;
|
|
823
803
|
}
|
|
824
804
|
context.report({
|
|
825
|
-
node,
|
|
826
|
-
messageId: "
|
|
805
|
+
node: secondArg,
|
|
806
|
+
messageId: "invalidConstructId"
|
|
827
807
|
});
|
|
828
808
|
};
|
|
829
809
|
const isInsideLoop = (node) => {
|
|
@@ -859,7 +839,7 @@ const pascalCaseConstructId = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
|
859
839
|
description: "Enforce PascalCase for Construct ID."
|
|
860
840
|
},
|
|
861
841
|
messages: {
|
|
862
|
-
|
|
842
|
+
invalidConstructId: "Construct ID must be PascalCase."
|
|
863
843
|
},
|
|
864
844
|
schema: [],
|
|
865
845
|
fixable: "code"
|
|
@@ -892,8 +872,8 @@ const validateConstructId = (node, context) => {
|
|
|
892
872
|
const quote = secondArg.raw?.startsWith('"') ? QUOTE_TYPE.DOUBLE : QUOTE_TYPE.SINGLE;
|
|
893
873
|
if (isPascalCase(secondArg.value)) return;
|
|
894
874
|
context.report({
|
|
895
|
-
node,
|
|
896
|
-
messageId: "
|
|
875
|
+
node: secondArg,
|
|
876
|
+
messageId: "invalidConstructId",
|
|
897
877
|
fix: (fixer) => {
|
|
898
878
|
const pascalCaseValue = toPascalCase(secondArg.value);
|
|
899
879
|
return fixer.replaceText(secondArg, `${quote}${pascalCaseValue}${quote}`);
|
|
@@ -1020,7 +1000,7 @@ const requirePassingThis = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
|
1020
1000
|
description: "Require passing `this` in a constructor."
|
|
1021
1001
|
},
|
|
1022
1002
|
messages: {
|
|
1023
|
-
|
|
1003
|
+
missingPassingThis: "Require passing `this` in a constructor."
|
|
1024
1004
|
},
|
|
1025
1005
|
schema: [
|
|
1026
1006
|
{
|
|
@@ -1056,8 +1036,8 @@ const requirePassingThis = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
|
1056
1036
|
if (constructorPropertyNames[0] !== "scope") return;
|
|
1057
1037
|
if (!options.allowNonThisAndDisallowScope) {
|
|
1058
1038
|
context.report({
|
|
1059
|
-
node,
|
|
1060
|
-
messageId: "
|
|
1039
|
+
node: argument,
|
|
1040
|
+
messageId: "missingPassingThis",
|
|
1061
1041
|
fix: (fixer) => {
|
|
1062
1042
|
return fixer.replaceText(argument, "this");
|
|
1063
1043
|
}
|
|
@@ -1066,8 +1046,8 @@ const requirePassingThis = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
|
1066
1046
|
}
|
|
1067
1047
|
if (argument.type === utils.AST_NODE_TYPES.Identifier && argument.name === "scope") {
|
|
1068
1048
|
context.report({
|
|
1069
|
-
node,
|
|
1070
|
-
messageId: "
|
|
1049
|
+
node: argument,
|
|
1050
|
+
messageId: "missingPassingThis",
|
|
1071
1051
|
fix: (fixer) => {
|
|
1072
1052
|
return fixer.replaceText(argument, "this");
|
|
1073
1053
|
}
|
|
@@ -1121,20 +1101,20 @@ const requirePropsDefaultDoc = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
|
1121
1101
|
});
|
|
1122
1102
|
|
|
1123
1103
|
const rules = {
|
|
1124
|
-
"
|
|
1104
|
+
"construct-constructor-property": constructConstructorProperty,
|
|
1105
|
+
"no-construct-in-interface": noConstructInInterface,
|
|
1106
|
+
"no-construct-in-public-property-of-construct": noConstructInPublicPropertyOfConstruct,
|
|
1125
1107
|
"no-construct-stack-suffix": noConstructStackSuffix,
|
|
1108
|
+
"no-import-private": noImportPrivate,
|
|
1109
|
+
"no-mutable-property-of-props-interface": noMutablePropertyOfPropsInterface,
|
|
1110
|
+
"no-mutable-public-property-of-construct": noMutablePublicPropertyOfConstruct,
|
|
1126
1111
|
"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
1112
|
"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,
|
|
1113
|
+
"pascal-case-construct-id": pascalCaseConstructId,
|
|
1136
1114
|
"props-name-convention": propsNameConvention,
|
|
1137
|
-
"
|
|
1115
|
+
"require-jsdoc": requireJSDoc,
|
|
1116
|
+
"require-passing-this": requirePassingThis,
|
|
1117
|
+
"require-props-default-doc": requirePropsDefaultDoc
|
|
1138
1118
|
};
|
|
1139
1119
|
const cdkPlugin = {
|
|
1140
1120
|
meta: { name, version },
|
|
@@ -1155,38 +1135,38 @@ const createFlatConfig = (rules2) => {
|
|
|
1155
1135
|
};
|
|
1156
1136
|
};
|
|
1157
1137
|
const recommended = createFlatConfig({
|
|
1158
|
-
"cdk/
|
|
1138
|
+
"cdk/construct-constructor-property": "error",
|
|
1139
|
+
"cdk/no-construct-in-interface": "error",
|
|
1140
|
+
"cdk/no-construct-in-public-property-of-construct": "error",
|
|
1159
1141
|
"cdk/no-construct-stack-suffix": "error",
|
|
1142
|
+
"cdk/no-mutable-property-of-props-interface": "warn",
|
|
1143
|
+
"cdk/no-mutable-public-property-of-construct": "warn",
|
|
1160
1144
|
"cdk/no-parent-name-construct-id-match": [
|
|
1161
1145
|
"error",
|
|
1162
1146
|
{ disallowContainingParentName: false }
|
|
1163
1147
|
],
|
|
1164
|
-
"cdk/no-public-class-fields": "error",
|
|
1165
|
-
"cdk/pascal-case-construct-id": "error",
|
|
1166
|
-
"cdk/require-passing-this": ["error", { allowNonThisAndDisallowScope: true }],
|
|
1167
1148
|
"cdk/no-variable-construct-id": "error",
|
|
1168
|
-
"cdk/
|
|
1169
|
-
"cdk/
|
|
1170
|
-
"cdk/construct-constructor-property": "error"
|
|
1149
|
+
"cdk/pascal-case-construct-id": "error",
|
|
1150
|
+
"cdk/require-passing-this": ["error", { allowNonThisAndDisallowScope: true }]
|
|
1171
1151
|
});
|
|
1172
1152
|
const strict = createFlatConfig({
|
|
1173
|
-
"cdk/
|
|
1153
|
+
"cdk/construct-constructor-property": "error",
|
|
1154
|
+
"cdk/no-construct-in-interface": "error",
|
|
1155
|
+
"cdk/no-construct-in-public-property-of-construct": "error",
|
|
1174
1156
|
"cdk/no-construct-stack-suffix": "error",
|
|
1157
|
+
"cdk/no-import-private": "error",
|
|
1158
|
+
"cdk/no-mutable-property-of-props-interface": "error",
|
|
1159
|
+
"cdk/no-mutable-public-property-of-construct": "error",
|
|
1175
1160
|
"cdk/no-parent-name-construct-id-match": [
|
|
1176
1161
|
"error",
|
|
1177
1162
|
{ disallowContainingParentName: true }
|
|
1178
1163
|
],
|
|
1179
|
-
"cdk/no-public-class-fields": "error",
|
|
1180
|
-
"cdk/pascal-case-construct-id": "error",
|
|
1181
|
-
"cdk/require-passing-this": "error",
|
|
1182
1164
|
"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",
|
|
1165
|
+
"cdk/pascal-case-construct-id": "error",
|
|
1188
1166
|
"cdk/props-name-convention": "error",
|
|
1189
|
-
"cdk/
|
|
1167
|
+
"cdk/require-jsdoc": "error",
|
|
1168
|
+
"cdk/require-passing-this": "error",
|
|
1169
|
+
"cdk/require-props-default-doc": "error"
|
|
1190
1170
|
});
|
|
1191
1171
|
const configs = {
|
|
1192
1172
|
recommended,
|