eslint-cdk-plugin 1.1.1 → 2.0.1
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 +6 -17
- package/dist/index.cjs +237 -86
- package/dist/index.d.ts +77 -30
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +237 -86
- package/package.json +14 -13
- package/src/{types/symbolFlags.ts → constants/tsInternalFlags.ts} +7 -7
- package/src/index.ts +59 -34
- package/src/rules/construct-constructor-property.ts +117 -0
- package/src/rules/no-class-in-interface.ts +5 -3
- package/src/rules/no-construct-stack-suffix.ts +53 -9
- package/src/rules/no-parent-name-construct-id-match.ts +1 -1
- package/src/rules/no-public-class-fields.ts +9 -3
- package/src/rules/no-variable-construct-id.ts +19 -0
- package/src/rules/pascal-case-construct-id.ts +1 -1
- package/src/rules/require-passing-this.ts +62 -11
- package/src/utils/parseType.ts +9 -3
- package/src/utils/typeCheck.ts +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,15 +1,103 @@
|
|
|
1
|
+
import tsParser from '@typescript-eslint/parser';
|
|
1
2
|
import { ESLintUtils, AST_NODE_TYPES, AST_TOKEN_TYPES } from '@typescript-eslint/utils';
|
|
2
3
|
import * as path from 'path';
|
|
3
4
|
|
|
4
|
-
var
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
var name = "eslint-cdk-plugin";
|
|
6
|
+
var version = "2.0.0";
|
|
7
|
+
|
|
8
|
+
const isConstructOrStackType = (type, ignoredClasses = ["App", "Stage"]) => {
|
|
9
|
+
if (ignoredClasses.includes(type.symbol?.name ?? "")) return false;
|
|
10
|
+
return isTargetSuperClassType(
|
|
11
|
+
type,
|
|
12
|
+
["Construct", "Stack"],
|
|
13
|
+
isConstructOrStackType
|
|
14
|
+
);
|
|
15
|
+
};
|
|
16
|
+
const isConstructType = (type, ignoredClasses = ["App", "Stage", "Stack"]) => {
|
|
17
|
+
if (ignoredClasses.includes(type.symbol?.name ?? "")) return false;
|
|
18
|
+
return isTargetSuperClassType(type, ["Construct"], isConstructType);
|
|
19
|
+
};
|
|
20
|
+
const isTargetSuperClassType = (type, targetSuperClasses, typeCheckFunction) => {
|
|
21
|
+
if (!type.symbol) return false;
|
|
22
|
+
if (targetSuperClasses.some((suffix) => type.symbol.name.endsWith(suffix))) {
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
const baseTypes = type.getBaseTypes() ?? [];
|
|
26
|
+
return baseTypes.some((baseType) => typeCheckFunction(baseType));
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const constructConstructorProperty = ESLintUtils.RuleCreator.withoutDocs(
|
|
30
|
+
{
|
|
31
|
+
meta: {
|
|
32
|
+
type: "problem",
|
|
33
|
+
docs: {
|
|
34
|
+
description: "Enforces that constructors of classes extending Construct have the property names 'scope, id' or 'scope, id, props'"
|
|
35
|
+
},
|
|
36
|
+
messages: {
|
|
37
|
+
invalidConstructorProperty: "Constructor of a class extending Construct must have the property names 'scope, id' or 'scope, id, props'"
|
|
38
|
+
},
|
|
39
|
+
schema: []
|
|
40
|
+
},
|
|
41
|
+
defaultOptions: [],
|
|
42
|
+
create(context) {
|
|
43
|
+
const parserServices = ESLintUtils.getParserServices(context);
|
|
44
|
+
return {
|
|
45
|
+
ClassDeclaration(node) {
|
|
46
|
+
const type = parserServices.getTypeAtLocation(node);
|
|
47
|
+
if (!isConstructType(type)) return;
|
|
48
|
+
const constructor = node.body.body.find(
|
|
49
|
+
(member) => member.type === AST_NODE_TYPES.MethodDefinition && member.kind === "constructor"
|
|
50
|
+
);
|
|
51
|
+
if (!constructor) return;
|
|
52
|
+
validateConstructorProperty(constructor, context);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
);
|
|
58
|
+
const validateConstructorProperty = (constructor, context) => {
|
|
59
|
+
const params = constructor.value.params;
|
|
60
|
+
if (params.length < 2) {
|
|
61
|
+
context.report({
|
|
62
|
+
node: constructor,
|
|
63
|
+
messageId: "invalidConstructorProperty"
|
|
64
|
+
});
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const firstParam = params[0];
|
|
68
|
+
if (firstParam.type === AST_NODE_TYPES.Identifier && firstParam.name !== "scope") {
|
|
69
|
+
context.report({
|
|
70
|
+
node: constructor,
|
|
71
|
+
messageId: "invalidConstructorProperty"
|
|
72
|
+
});
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const secondParam = params[1];
|
|
76
|
+
if (secondParam.type === AST_NODE_TYPES.Identifier && secondParam.name !== "id") {
|
|
77
|
+
context.report({
|
|
78
|
+
node: constructor,
|
|
79
|
+
messageId: "invalidConstructorProperty"
|
|
80
|
+
});
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (params.length < 3) return;
|
|
84
|
+
const thirdParam = params[2];
|
|
85
|
+
if (thirdParam.type === AST_NODE_TYPES.Identifier && thirdParam.name !== "props") {
|
|
86
|
+
context.report({
|
|
87
|
+
node: constructor,
|
|
88
|
+
messageId: "invalidConstructorProperty"
|
|
89
|
+
});
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const SYMBOL_FLAGS = {
|
|
95
|
+
CLASS: 32
|
|
96
|
+
};
|
|
97
|
+
const SYNTAX_KIND = {
|
|
98
|
+
CLASS_DECLARATION: 263,
|
|
99
|
+
CONSTRUCTOR: 176
|
|
100
|
+
};
|
|
13
101
|
|
|
14
102
|
const noClassInInterface = ESLintUtils.RuleCreator.withoutDocs({
|
|
15
103
|
meta: {
|
|
@@ -33,7 +121,7 @@ const noClassInInterface = ESLintUtils.RuleCreator.withoutDocs({
|
|
|
33
121
|
}
|
|
34
122
|
const type = parserServices.getTypeAtLocation(property);
|
|
35
123
|
if (!type.symbol) continue;
|
|
36
|
-
const isClass = type.symbol.flags ===
|
|
124
|
+
const isClass = type.symbol.flags === SYMBOL_FLAGS.CLASS;
|
|
37
125
|
if (!isClass) continue;
|
|
38
126
|
context.report({
|
|
39
127
|
node: property,
|
|
@@ -69,33 +157,16 @@ const getConstructorPropertyNames = (type) => {
|
|
|
69
157
|
return constructor.parameters.map((param) => param.name.getText());
|
|
70
158
|
};
|
|
71
159
|
const isClassDeclaration = (declaration) => {
|
|
72
|
-
return declaration.kind ===
|
|
160
|
+
return declaration.kind === SYNTAX_KIND.CLASS_DECLARATION;
|
|
73
161
|
};
|
|
74
162
|
const isConstructorDeclaration = (node) => {
|
|
75
|
-
return node.kind ===
|
|
163
|
+
return node.kind === SYNTAX_KIND.CONSTRUCTOR;
|
|
76
164
|
};
|
|
77
165
|
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
type,
|
|
82
|
-
["Construct", "Stack"],
|
|
83
|
-
isConstructOrStackType
|
|
84
|
-
);
|
|
85
|
-
};
|
|
86
|
-
const isConstructType = (type, ignoredClasses = ["App", "Stage", "Stack"]) => {
|
|
87
|
-
if (ignoredClasses.includes(type.symbol?.name ?? "")) return false;
|
|
88
|
-
return isTargetSuperClassType(type, ["Construct"], isConstructType);
|
|
89
|
-
};
|
|
90
|
-
const isTargetSuperClassType = (type, targetSuperClasses, typeCheckFunction) => {
|
|
91
|
-
if (!type.symbol) return false;
|
|
92
|
-
if (targetSuperClasses.some((suffix) => type.symbol.name.endsWith(suffix))) {
|
|
93
|
-
return true;
|
|
94
|
-
}
|
|
95
|
-
const baseTypes = type.getBaseTypes() || [];
|
|
96
|
-
return baseTypes.some((baseType) => typeCheckFunction(baseType));
|
|
166
|
+
const SUFFIX_TYPE = {
|
|
167
|
+
CONSTRUCT: "Construct",
|
|
168
|
+
STACK: "Stack"
|
|
97
169
|
};
|
|
98
|
-
|
|
99
170
|
const noConstructStackSuffix = ESLintUtils.RuleCreator.withoutDocs({
|
|
100
171
|
meta: {
|
|
101
172
|
type: "problem",
|
|
@@ -105,11 +176,33 @@ const noConstructStackSuffix = ESLintUtils.RuleCreator.withoutDocs({
|
|
|
105
176
|
messages: {
|
|
106
177
|
noConstructStackSuffix: "{{ classType }} ID '{{ id }}' should not include {{ suffix }} suffix."
|
|
107
178
|
},
|
|
108
|
-
schema: [
|
|
179
|
+
schema: [
|
|
180
|
+
{
|
|
181
|
+
type: "object",
|
|
182
|
+
properties: {
|
|
183
|
+
disallowedSuffixes: {
|
|
184
|
+
type: "array",
|
|
185
|
+
items: {
|
|
186
|
+
type: "string",
|
|
187
|
+
enum: [SUFFIX_TYPE.CONSTRUCT, SUFFIX_TYPE.STACK]
|
|
188
|
+
},
|
|
189
|
+
uniqueItems: true
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
additionalProperties: false
|
|
193
|
+
}
|
|
194
|
+
]
|
|
109
195
|
},
|
|
110
|
-
defaultOptions: [
|
|
196
|
+
defaultOptions: [
|
|
197
|
+
{
|
|
198
|
+
disallowedSuffixes: [SUFFIX_TYPE.CONSTRUCT, SUFFIX_TYPE.STACK]
|
|
199
|
+
}
|
|
200
|
+
],
|
|
111
201
|
create(context) {
|
|
112
202
|
const parserServices = ESLintUtils.getParserServices(context);
|
|
203
|
+
const options = context.options[0] ?? {
|
|
204
|
+
disallowedSuffixes: [SUFFIX_TYPE.CONSTRUCT, SUFFIX_TYPE.STACK]
|
|
205
|
+
};
|
|
113
206
|
return {
|
|
114
207
|
NewExpression(node) {
|
|
115
208
|
const type = parserServices.getTypeAtLocation(node);
|
|
@@ -118,35 +211,36 @@ const noConstructStackSuffix = ESLintUtils.RuleCreator.withoutDocs({
|
|
|
118
211
|
}
|
|
119
212
|
const constructorPropertyNames = getConstructorPropertyNames(type);
|
|
120
213
|
if (constructorPropertyNames[1] !== "id") return;
|
|
121
|
-
validateConstructId$3(node, context);
|
|
214
|
+
validateConstructId$3(node, context, options);
|
|
122
215
|
}
|
|
123
216
|
};
|
|
124
217
|
}
|
|
125
218
|
});
|
|
126
|
-
const validateConstructId$3 = (node, context) => {
|
|
219
|
+
const validateConstructId$3 = (node, context, options) => {
|
|
127
220
|
const secondArg = node.arguments[1];
|
|
128
221
|
if (secondArg.type !== AST_NODE_TYPES.Literal || typeof secondArg.value !== "string") {
|
|
129
222
|
return;
|
|
130
223
|
}
|
|
131
224
|
const formattedConstructId = toPascalCase(secondArg.value);
|
|
132
|
-
|
|
225
|
+
const disallowedSuffixes = options.disallowedSuffixes;
|
|
226
|
+
if (disallowedSuffixes.includes(SUFFIX_TYPE.CONSTRUCT) && formattedConstructId.endsWith(SUFFIX_TYPE.CONSTRUCT)) {
|
|
133
227
|
context.report({
|
|
134
228
|
node,
|
|
135
229
|
messageId: "noConstructStackSuffix",
|
|
136
230
|
data: {
|
|
137
231
|
classType: "Construct",
|
|
138
232
|
id: secondArg.value,
|
|
139
|
-
suffix:
|
|
233
|
+
suffix: SUFFIX_TYPE.CONSTRUCT
|
|
140
234
|
}
|
|
141
235
|
});
|
|
142
|
-
} else if (formattedConstructId.endsWith(
|
|
236
|
+
} else if (disallowedSuffixes.includes(SUFFIX_TYPE.STACK) && formattedConstructId.endsWith(SUFFIX_TYPE.STACK)) {
|
|
143
237
|
context.report({
|
|
144
238
|
node,
|
|
145
239
|
messageId: "noConstructStackSuffix",
|
|
146
240
|
data: {
|
|
147
241
|
classType: "Stack",
|
|
148
242
|
id: secondArg.value,
|
|
149
|
-
suffix:
|
|
243
|
+
suffix: SUFFIX_TYPE.STACK
|
|
150
244
|
}
|
|
151
245
|
});
|
|
152
246
|
}
|
|
@@ -559,7 +653,7 @@ const validateClassMember = (node, context, parserServices) => {
|
|
|
559
653
|
if (!member.typeAnnotation) continue;
|
|
560
654
|
const type = parserServices.getTypeAtLocation(member);
|
|
561
655
|
if (!type.symbol) continue;
|
|
562
|
-
const isClass = type.symbol.flags ===
|
|
656
|
+
const isClass = type.symbol.flags === SYMBOL_FLAGS.CLASS;
|
|
563
657
|
if (!isClass) continue;
|
|
564
658
|
context.report({
|
|
565
659
|
node: member,
|
|
@@ -582,7 +676,7 @@ const validateConstructorParameterProperty = (constructor, context, parserServic
|
|
|
582
676
|
if (!param.parameter.typeAnnotation) continue;
|
|
583
677
|
const type = parserServices.getTypeAtLocation(param);
|
|
584
678
|
if (!type.symbol) continue;
|
|
585
|
-
const isClass = type.symbol.flags ===
|
|
679
|
+
const isClass = type.symbol.flags === SYMBOL_FLAGS.CLASS;
|
|
586
680
|
if (!isClass) continue;
|
|
587
681
|
context.report({
|
|
588
682
|
node: param,
|
|
@@ -640,6 +734,17 @@ const isInsideLoop = (node) => {
|
|
|
640
734
|
if (current.type === AST_NODE_TYPES.ForStatement || current.type === AST_NODE_TYPES.ForInStatement || current.type === AST_NODE_TYPES.ForOfStatement || current.type === AST_NODE_TYPES.WhileStatement || current.type === AST_NODE_TYPES.DoWhileStatement) {
|
|
641
735
|
return true;
|
|
642
736
|
}
|
|
737
|
+
if (current.type === AST_NODE_TYPES.CallExpression && current.callee.type === AST_NODE_TYPES.MemberExpression && current.callee.property.type === AST_NODE_TYPES.Identifier && [
|
|
738
|
+
"forEach",
|
|
739
|
+
"map",
|
|
740
|
+
"filter",
|
|
741
|
+
"reduce",
|
|
742
|
+
"flatMap",
|
|
743
|
+
"some",
|
|
744
|
+
"every"
|
|
745
|
+
].includes(current.callee.property.name)) {
|
|
746
|
+
return true;
|
|
747
|
+
}
|
|
643
748
|
current = current.parent;
|
|
644
749
|
}
|
|
645
750
|
return false;
|
|
@@ -819,11 +924,29 @@ const requirePassingThis = ESLintUtils.RuleCreator.withoutDocs({
|
|
|
819
924
|
messages: {
|
|
820
925
|
requirePassingThis: "Require passing `this` in a constructor."
|
|
821
926
|
},
|
|
822
|
-
schema: [
|
|
927
|
+
schema: [
|
|
928
|
+
{
|
|
929
|
+
type: "object",
|
|
930
|
+
properties: {
|
|
931
|
+
allowNonThisAndDisallowScope: {
|
|
932
|
+
type: "boolean",
|
|
933
|
+
default: false
|
|
934
|
+
}
|
|
935
|
+
},
|
|
936
|
+
additionalProperties: false
|
|
937
|
+
}
|
|
938
|
+
],
|
|
823
939
|
fixable: "code"
|
|
824
940
|
},
|
|
825
|
-
defaultOptions: [
|
|
941
|
+
defaultOptions: [
|
|
942
|
+
{
|
|
943
|
+
allowNonThisAndDisallowScope: false
|
|
944
|
+
}
|
|
945
|
+
],
|
|
826
946
|
create(context) {
|
|
947
|
+
const options = context.options[0] || {
|
|
948
|
+
allowNonThisAndDisallowScope: false
|
|
949
|
+
};
|
|
827
950
|
const parserServices = ESLintUtils.getParserServices(context);
|
|
828
951
|
return {
|
|
829
952
|
NewExpression(node) {
|
|
@@ -833,13 +956,25 @@ const requirePassingThis = ESLintUtils.RuleCreator.withoutDocs({
|
|
|
833
956
|
if (argument.type === AST_NODE_TYPES.ThisExpression) return;
|
|
834
957
|
const constructorPropertyNames = getConstructorPropertyNames(type);
|
|
835
958
|
if (constructorPropertyNames[0] !== "scope") return;
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
959
|
+
if (!options.allowNonThisAndDisallowScope) {
|
|
960
|
+
context.report({
|
|
961
|
+
node,
|
|
962
|
+
messageId: "requirePassingThis",
|
|
963
|
+
fix: (fixer) => {
|
|
964
|
+
return fixer.replaceText(argument, "this");
|
|
965
|
+
}
|
|
966
|
+
});
|
|
967
|
+
return;
|
|
968
|
+
}
|
|
969
|
+
if (argument.type === AST_NODE_TYPES.Identifier && argument.name === "scope") {
|
|
970
|
+
context.report({
|
|
971
|
+
node,
|
|
972
|
+
messageId: "requirePassingThis",
|
|
973
|
+
fix: (fixer) => {
|
|
974
|
+
return fixer.replaceText(argument, "this");
|
|
975
|
+
}
|
|
976
|
+
});
|
|
977
|
+
}
|
|
843
978
|
}
|
|
844
979
|
};
|
|
845
980
|
}
|
|
@@ -893,49 +1028,65 @@ const rules = {
|
|
|
893
1028
|
"no-parent-name-construct-id-match": noParentNameConstructIdMatch,
|
|
894
1029
|
"no-public-class-fields": noPublicClassFields,
|
|
895
1030
|
"pascal-case-construct-id": pascalCaseConstructId,
|
|
896
|
-
"no-mutable-public-fields": noMutablePublicFields,
|
|
897
|
-
"no-mutable-props-interface": noMutablePropsInterface,
|
|
898
1031
|
"require-passing-this": requirePassingThis,
|
|
899
1032
|
"no-variable-construct-id": noVariableConstructId,
|
|
1033
|
+
"no-mutable-public-fields": noMutablePublicFields,
|
|
1034
|
+
"no-mutable-props-interface": noMutablePropsInterface,
|
|
1035
|
+
"construct-constructor-property": constructConstructorProperty,
|
|
900
1036
|
"require-jsdoc": requireJSDoc,
|
|
901
1037
|
"require-props-default-doc": requirePropsDefaultDoc,
|
|
902
1038
|
"props-name-convention": propsNameConvention,
|
|
903
1039
|
"no-import-private": noImportPrivate
|
|
904
1040
|
};
|
|
1041
|
+
const cdkPlugin = {
|
|
1042
|
+
meta: { name, version },
|
|
1043
|
+
rules
|
|
1044
|
+
};
|
|
1045
|
+
const createFlatConfig = (rules2) => {
|
|
1046
|
+
return {
|
|
1047
|
+
languageOptions: {
|
|
1048
|
+
parser: tsParser,
|
|
1049
|
+
parserOptions: {
|
|
1050
|
+
projectService: true
|
|
1051
|
+
}
|
|
1052
|
+
},
|
|
1053
|
+
plugins: {
|
|
1054
|
+
cdk: cdkPlugin
|
|
1055
|
+
},
|
|
1056
|
+
rules: rules2
|
|
1057
|
+
};
|
|
1058
|
+
};
|
|
1059
|
+
const recommended = createFlatConfig({
|
|
1060
|
+
"cdk/no-class-in-interface": "error",
|
|
1061
|
+
"cdk/no-construct-stack-suffix": "error",
|
|
1062
|
+
"cdk/no-parent-name-construct-id-match": "error",
|
|
1063
|
+
"cdk/no-public-class-fields": "error",
|
|
1064
|
+
"cdk/pascal-case-construct-id": "error",
|
|
1065
|
+
"cdk/require-passing-this": ["error", { allowNonThisAndDisallowScope: true }],
|
|
1066
|
+
"cdk/no-variable-construct-id": "error",
|
|
1067
|
+
"cdk/no-mutable-public-fields": "warn",
|
|
1068
|
+
"cdk/no-mutable-props-interface": "warn",
|
|
1069
|
+
"cdk/construct-constructor-property": "error"
|
|
1070
|
+
});
|
|
1071
|
+
const strict = createFlatConfig({
|
|
1072
|
+
"cdk/no-class-in-interface": "error",
|
|
1073
|
+
"cdk/no-construct-stack-suffix": "error",
|
|
1074
|
+
"cdk/no-parent-name-construct-id-match": "error",
|
|
1075
|
+
"cdk/no-public-class-fields": "error",
|
|
1076
|
+
"cdk/pascal-case-construct-id": "error",
|
|
1077
|
+
"cdk/require-passing-this": "error",
|
|
1078
|
+
"cdk/no-variable-construct-id": "error",
|
|
1079
|
+
"cdk/no-mutable-public-fields": "error",
|
|
1080
|
+
"cdk/no-mutable-props-interface": "error",
|
|
1081
|
+
"cdk/construct-constructor-property": "error",
|
|
1082
|
+
"cdk/require-jsdoc": "error",
|
|
1083
|
+
"cdk/require-props-default-doc": "error",
|
|
1084
|
+
"cdk/props-name-convention": "error",
|
|
1085
|
+
"cdk/no-import-private": "error"
|
|
1086
|
+
});
|
|
905
1087
|
const configs = {
|
|
906
|
-
recommended
|
|
907
|
-
|
|
908
|
-
rules: {
|
|
909
|
-
"cdk/no-class-in-interface": "error",
|
|
910
|
-
"cdk/no-construct-stack-suffix": "error",
|
|
911
|
-
"cdk/no-parent-name-construct-id-match": "error",
|
|
912
|
-
"cdk/no-public-class-fields": "error",
|
|
913
|
-
"cdk/pascal-case-construct-id": "error",
|
|
914
|
-
"cdk/require-passing-this": "error",
|
|
915
|
-
"cdk/no-variable-construct-id": "error",
|
|
916
|
-
"cdk/no-mutable-public-fields": "warn",
|
|
917
|
-
"cdk/no-mutable-props-interface": "warn",
|
|
918
|
-
"cdk/props-name-convention": "warn"
|
|
919
|
-
}
|
|
920
|
-
},
|
|
921
|
-
strict: {
|
|
922
|
-
plugins: ["cdk"],
|
|
923
|
-
rules: {
|
|
924
|
-
"cdk/no-class-in-interface": "error",
|
|
925
|
-
"cdk/no-construct-stack-suffix": "error",
|
|
926
|
-
"cdk/no-parent-name-construct-id-match": "error",
|
|
927
|
-
"cdk/no-public-class-fields": "error",
|
|
928
|
-
"cdk/pascal-case-construct-id": "error",
|
|
929
|
-
"cdk/require-passing-this": "error",
|
|
930
|
-
"cdk/no-variable-construct-id": "error",
|
|
931
|
-
"cdk/no-mutable-public-fields": "error",
|
|
932
|
-
"cdk/no-mutable-props-interface": "error",
|
|
933
|
-
"cdk/no-import-private": "error",
|
|
934
|
-
"cdk/require-props-default-doc": "error",
|
|
935
|
-
"cdk/props-name-convention": "error",
|
|
936
|
-
"cdk/require-jsdoc": "error"
|
|
937
|
-
}
|
|
938
|
-
}
|
|
1088
|
+
recommended,
|
|
1089
|
+
strict
|
|
939
1090
|
};
|
|
940
1091
|
const eslintCdkPlugin = {
|
|
941
1092
|
rules,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-cdk-plugin",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "eslint plugin for AWS CDK projects",
|
|
5
5
|
"main": "./dist/index.mjs",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
"build": "sh scripts/build.sh",
|
|
21
21
|
"test": "vitest --run",
|
|
22
22
|
"lint": "eslint --fix --config eslint.config.js",
|
|
23
|
-
"
|
|
23
|
+
"check": "tsc --noEmit",
|
|
24
|
+
"pack": "pnpm run build && npm pack",
|
|
24
25
|
"release:minor": "standard-version --release-as minor",
|
|
25
26
|
"release:major": "standard-version --release-as major",
|
|
26
27
|
"release:patch": "standard-version --release-as patch",
|
|
@@ -29,23 +30,23 @@
|
|
|
29
30
|
"docs:preview": "cd ./docs && pnpm install && pnpm run preview"
|
|
30
31
|
},
|
|
31
32
|
"devDependencies": {
|
|
32
|
-
"@eslint/js": "^9.
|
|
33
|
-
"@types/
|
|
34
|
-
"@
|
|
35
|
-
"
|
|
36
|
-
"eslint": "9.10.0",
|
|
33
|
+
"@eslint/js": "^9.22.0",
|
|
34
|
+
"@types/node": "^22.13.10",
|
|
35
|
+
"@typescript-eslint/rule-tester": "^8.26.0",
|
|
36
|
+
"eslint": "9.22.0",
|
|
37
37
|
"eslint-plugin-import": "^2.31.0",
|
|
38
|
-
"pkgroll": "^2.
|
|
38
|
+
"pkgroll": "^2.11.2",
|
|
39
39
|
"standard-version": "^9.5.0",
|
|
40
|
-
"typescript": "^5.
|
|
41
|
-
"typescript-eslint": "^8.
|
|
42
|
-
"vitest": "^
|
|
40
|
+
"typescript": "^5.8.2",
|
|
41
|
+
"typescript-eslint": "^8.26.0",
|
|
42
|
+
"vitest": "^3.0.8"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@typescript-eslint/
|
|
45
|
+
"@typescript-eslint/parser": "^8.26.0",
|
|
46
|
+
"@typescript-eslint/utils": "^8.26.0"
|
|
46
47
|
},
|
|
47
48
|
"volta": {
|
|
48
|
-
"node": "22.
|
|
49
|
+
"node": "22.14.0"
|
|
49
50
|
},
|
|
50
51
|
"files": [
|
|
51
52
|
"dist",
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Implementing `SymbolFlags` defined in typescript on your own, in order not to include TypeScript in dependencies
|
|
3
3
|
*/
|
|
4
|
-
export
|
|
5
|
-
|
|
6
|
-
}
|
|
4
|
+
export const SYMBOL_FLAGS = {
|
|
5
|
+
CLASS: 32,
|
|
6
|
+
} as const;
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Implementing `SyntaxKind` defined in typescript on your own, in order not to include TypeScript in dependencies
|
|
10
10
|
*/
|
|
11
|
-
export
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
11
|
+
export const SYNTAX_KIND = {
|
|
12
|
+
CLASS_DECLARATION: 263,
|
|
13
|
+
CONSTRUCTOR: 176,
|
|
14
|
+
} as const;
|
package/src/index.ts
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import tsParser from "@typescript-eslint/parser";
|
|
2
|
+
|
|
3
|
+
import { name, version } from "../package.json";
|
|
4
|
+
|
|
5
|
+
import { constructConstructorProperty } from "./rules/construct-constructor-property";
|
|
1
6
|
import { noClassInInterface } from "./rules/no-class-in-interface";
|
|
2
7
|
import { noConstructStackSuffix } from "./rules/no-construct-stack-suffix";
|
|
3
8
|
import { noImportPrivate } from "./rules/no-import-private";
|
|
@@ -18,50 +23,70 @@ const rules = {
|
|
|
18
23
|
"no-parent-name-construct-id-match": noParentNameConstructIdMatch,
|
|
19
24
|
"no-public-class-fields": noPublicClassFields,
|
|
20
25
|
"pascal-case-construct-id": pascalCaseConstructId,
|
|
21
|
-
"no-mutable-public-fields": noMutablePublicFields,
|
|
22
|
-
"no-mutable-props-interface": noMutablePropsInterface,
|
|
23
26
|
"require-passing-this": requirePassingThis,
|
|
24
27
|
"no-variable-construct-id": noVariableConstructId,
|
|
28
|
+
"no-mutable-public-fields": noMutablePublicFields,
|
|
29
|
+
"no-mutable-props-interface": noMutablePropsInterface,
|
|
30
|
+
"construct-constructor-property": constructConstructorProperty,
|
|
25
31
|
"require-jsdoc": requireJSDoc,
|
|
26
32
|
"require-props-default-doc": requirePropsDefaultDoc,
|
|
27
33
|
"props-name-convention": propsNameConvention,
|
|
28
34
|
"no-import-private": noImportPrivate,
|
|
29
35
|
};
|
|
30
36
|
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"cdk/no-mutable-props-interface": "warn",
|
|
44
|
-
"cdk/props-name-convention": "warn",
|
|
37
|
+
const cdkPlugin = {
|
|
38
|
+
meta: { name, version },
|
|
39
|
+
rules,
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const createFlatConfig = (rules: Record<string, unknown>) => {
|
|
43
|
+
return {
|
|
44
|
+
languageOptions: {
|
|
45
|
+
parser: tsParser,
|
|
46
|
+
parserOptions: {
|
|
47
|
+
projectService: true,
|
|
48
|
+
},
|
|
45
49
|
},
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
plugins: ["cdk"],
|
|
49
|
-
rules: {
|
|
50
|
-
"cdk/no-class-in-interface": "error",
|
|
51
|
-
"cdk/no-construct-stack-suffix": "error",
|
|
52
|
-
"cdk/no-parent-name-construct-id-match": "error",
|
|
53
|
-
"cdk/no-public-class-fields": "error",
|
|
54
|
-
"cdk/pascal-case-construct-id": "error",
|
|
55
|
-
"cdk/require-passing-this": "error",
|
|
56
|
-
"cdk/no-variable-construct-id": "error",
|
|
57
|
-
"cdk/no-mutable-public-fields": "error",
|
|
58
|
-
"cdk/no-mutable-props-interface": "error",
|
|
59
|
-
"cdk/no-import-private": "error",
|
|
60
|
-
"cdk/require-props-default-doc": "error",
|
|
61
|
-
"cdk/props-name-convention": "error",
|
|
62
|
-
"cdk/require-jsdoc": "error",
|
|
50
|
+
plugins: {
|
|
51
|
+
cdk: cdkPlugin,
|
|
63
52
|
},
|
|
64
|
-
|
|
53
|
+
rules,
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const recommended = createFlatConfig({
|
|
58
|
+
"cdk/no-class-in-interface": "error",
|
|
59
|
+
"cdk/no-construct-stack-suffix": "error",
|
|
60
|
+
"cdk/no-parent-name-construct-id-match": "error",
|
|
61
|
+
"cdk/no-public-class-fields": "error",
|
|
62
|
+
"cdk/pascal-case-construct-id": "error",
|
|
63
|
+
"cdk/require-passing-this": ["error", { allowNonThisAndDisallowScope: true }],
|
|
64
|
+
"cdk/no-variable-construct-id": "error",
|
|
65
|
+
"cdk/no-mutable-public-fields": "warn",
|
|
66
|
+
"cdk/no-mutable-props-interface": "warn",
|
|
67
|
+
"cdk/construct-constructor-property": "error",
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const strict = createFlatConfig({
|
|
71
|
+
"cdk/no-class-in-interface": "error",
|
|
72
|
+
"cdk/no-construct-stack-suffix": "error",
|
|
73
|
+
"cdk/no-parent-name-construct-id-match": "error",
|
|
74
|
+
"cdk/no-public-class-fields": "error",
|
|
75
|
+
"cdk/pascal-case-construct-id": "error",
|
|
76
|
+
"cdk/require-passing-this": "error",
|
|
77
|
+
"cdk/no-variable-construct-id": "error",
|
|
78
|
+
"cdk/no-mutable-public-fields": "error",
|
|
79
|
+
"cdk/no-mutable-props-interface": "error",
|
|
80
|
+
"cdk/construct-constructor-property": "error",
|
|
81
|
+
"cdk/require-jsdoc": "error",
|
|
82
|
+
"cdk/require-props-default-doc": "error",
|
|
83
|
+
"cdk/props-name-convention": "error",
|
|
84
|
+
"cdk/no-import-private": "error",
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
const configs = {
|
|
88
|
+
recommended,
|
|
89
|
+
strict,
|
|
65
90
|
};
|
|
66
91
|
|
|
67
92
|
export { configs, rules };
|