eslint-cdk-plugin 0.3.2 → 1.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/CONTRIBUTING.md +105 -0
- package/README.md +51 -6
- package/VERSIONING_POLICY.md +34 -0
- package/assets/logo.png +0 -0
- package/dist/index.d.mts +31 -0
- package/dist/index.mjs +9 -2
- package/dist/index.mjs.map +1 -0
- package/dist/no-class-in-interface-props.d.mts +2 -0
- package/dist/{no-class-in-interface.mjs → no-class-in-interface-props.mjs} +13 -14
- package/dist/no-class-in-interface-props.mjs.map +1 -0
- package/dist/no-construct-stack-suffix.d.mts +2 -0
- package/dist/no-construct-stack-suffix.mjs +20 -148
- package/dist/no-construct-stack-suffix.mjs.map +1 -0
- package/dist/no-import-private.d.mts +2 -0
- package/dist/no-import-private.mjs +18 -24
- package/dist/no-import-private.mjs.map +1 -0
- package/dist/no-mutable-props-interface.d.mts +2 -0
- package/dist/no-mutable-props-interface.mjs +14 -19
- package/dist/no-mutable-props-interface.mjs.map +1 -0
- package/dist/no-mutable-public-fields.d.mts +2 -0
- package/dist/no-mutable-public-fields.mjs +26 -25
- package/dist/no-mutable-public-fields.mjs.map +1 -0
- package/dist/no-parent-name-construct-id-match.d.mts +2 -0
- package/dist/no-parent-name-construct-id-match.mjs +101 -140
- package/dist/no-parent-name-construct-id-match.mjs.map +1 -0
- package/dist/no-public-class-fields.d.mts +2 -0
- package/dist/no-public-class-fields.mjs +40 -46
- package/dist/no-public-class-fields.mjs.map +1 -0
- package/dist/no-variable-construct-id.d.mts +2 -0
- package/dist/no-variable-construct-id.mjs +63 -0
- package/dist/no-variable-construct-id.mjs.map +1 -0
- package/dist/pascal-case-construct-id.d.mts +2 -0
- package/dist/pascal-case-construct-id.mjs +40 -47
- package/dist/pascal-case-construct-id.mjs.map +1 -0
- package/dist/require-passing-this.d.mts +2 -0
- package/dist/require-passing-this.mjs +39 -0
- package/dist/require-passing-this.mjs.map +1 -0
- package/dist/utils/convertString.d.mts +1 -0
- package/dist/utils/convertString.mjs +4 -9
- package/dist/utils/convertString.mjs.map +1 -0
- package/dist/utils/typeCheck.d.mts +3 -0
- package/dist/utils/typeCheck.mjs +16 -0
- package/dist/utils/typeCheck.mjs.map +1 -0
- package/package.json +6 -3
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { ESLintUtils, } from "@typescript-eslint/utils";
|
|
1
|
+
import { AST_NODE_TYPES, ESLintUtils, } from "@typescript-eslint/utils";
|
|
2
2
|
import { SymbolFlags } from "typescript";
|
|
3
|
-
|
|
3
|
+
import { isConstructOrStackType } from "./utils/typeCheck.mjs";
|
|
4
|
+
export const noPublicClassFields = ESLintUtils.RuleCreator.withoutDocs({
|
|
4
5
|
meta: {
|
|
5
6
|
type: "problem",
|
|
6
7
|
docs: {
|
|
@@ -12,57 +13,54 @@ export var noPublicClassFields = ESLintUtils.RuleCreator.withoutDocs({
|
|
|
12
13
|
schema: [],
|
|
13
14
|
},
|
|
14
15
|
defaultOptions: [],
|
|
15
|
-
create
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
create(context) {
|
|
17
|
+
const parserServices = ESLintUtils.getParserServices(context);
|
|
18
|
+
const typeChecker = parserServices.program.getTypeChecker();
|
|
18
19
|
return {
|
|
19
|
-
ClassDeclaration
|
|
20
|
-
|
|
20
|
+
ClassDeclaration(node) {
|
|
21
|
+
const type = typeChecker.getTypeAtLocation(parserServices.esTreeNodeToTSNodeMap.get(node));
|
|
22
|
+
if (!isConstructOrStackType(type)) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
21
25
|
validateClassMember({
|
|
22
|
-
node
|
|
23
|
-
context
|
|
24
|
-
parserServices
|
|
25
|
-
typeChecker
|
|
26
|
-
});
|
|
27
|
-
// NOTE: Check constructor parameter properties
|
|
28
|
-
var constructor = node.body.body.find(function (member) {
|
|
29
|
-
return member.type === "MethodDefinition" && member.kind === "constructor";
|
|
26
|
+
node,
|
|
27
|
+
context,
|
|
28
|
+
parserServices,
|
|
29
|
+
typeChecker,
|
|
30
30
|
});
|
|
31
|
-
|
|
31
|
+
const constructor = node.body.body.find((member) => member.type === AST_NODE_TYPES.MethodDefinition &&
|
|
32
|
+
member.kind === "constructor");
|
|
33
|
+
if (!constructor ||
|
|
34
|
+
constructor.value.type !== AST_NODE_TYPES.FunctionExpression) {
|
|
32
35
|
return;
|
|
33
36
|
}
|
|
34
37
|
validateConstructorParameterProperty({
|
|
35
|
-
constructor
|
|
36
|
-
context
|
|
37
|
-
parserServices
|
|
38
|
-
typeChecker
|
|
38
|
+
constructor,
|
|
39
|
+
context,
|
|
40
|
+
parserServices,
|
|
41
|
+
typeChecker,
|
|
39
42
|
});
|
|
40
43
|
},
|
|
41
44
|
};
|
|
42
45
|
},
|
|
43
46
|
});
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
var member = _c[_i];
|
|
49
|
-
if (member.type !== "PropertyDefinition" ||
|
|
50
|
-
member.key.type !== "Identifier") {
|
|
47
|
+
const validateClassMember = ({ node, context, parserServices, typeChecker, }) => {
|
|
48
|
+
for (const member of node.body.body) {
|
|
49
|
+
if (member.type !== AST_NODE_TYPES.PropertyDefinition ||
|
|
50
|
+
member.key.type !== AST_NODE_TYPES.Identifier) {
|
|
51
51
|
continue;
|
|
52
52
|
}
|
|
53
|
-
|
|
54
|
-
if (["private", "protected"].includes((_b = member.accessibility) !== null && _b !== void 0 ? _b : "")) {
|
|
53
|
+
if (["private", "protected"].includes(member.accessibility ?? "")) {
|
|
55
54
|
continue;
|
|
56
55
|
}
|
|
57
|
-
// NOTE: Skip fields without type annotation
|
|
58
56
|
if (!member.typeAnnotation) {
|
|
59
57
|
continue;
|
|
60
58
|
}
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
const tsNode = parserServices.esTreeNodeToTSNodeMap.get(member);
|
|
60
|
+
const type = typeChecker.getTypeAtLocation(tsNode);
|
|
63
61
|
if (!type.symbol)
|
|
64
62
|
continue;
|
|
65
|
-
|
|
63
|
+
const isClass = type.symbol.flags === SymbolFlags.Class;
|
|
66
64
|
if (!isClass)
|
|
67
65
|
continue;
|
|
68
66
|
context.report({
|
|
@@ -75,28 +73,23 @@ var validateClassMember = function (_a) {
|
|
|
75
73
|
});
|
|
76
74
|
}
|
|
77
75
|
};
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
var param = _c[_i];
|
|
83
|
-
if (param.type !== "TSParameterProperty" ||
|
|
84
|
-
param.parameter.type !== "Identifier") {
|
|
76
|
+
const validateConstructorParameterProperty = ({ constructor, context, parserServices, typeChecker, }) => {
|
|
77
|
+
for (const param of constructor.value.params) {
|
|
78
|
+
if (param.type !== AST_NODE_TYPES.TSParameterProperty ||
|
|
79
|
+
param.parameter.type !== AST_NODE_TYPES.Identifier) {
|
|
85
80
|
continue;
|
|
86
81
|
}
|
|
87
|
-
|
|
88
|
-
if (["private", "protected"].includes((_b = param.accessibility) !== null && _b !== void 0 ? _b : "")) {
|
|
82
|
+
if (["private", "protected"].includes(param.accessibility ?? "")) {
|
|
89
83
|
continue;
|
|
90
84
|
}
|
|
91
|
-
// NOTE: Skip parameters without type annotation
|
|
92
85
|
if (!param.parameter.typeAnnotation) {
|
|
93
86
|
continue;
|
|
94
87
|
}
|
|
95
|
-
|
|
96
|
-
|
|
88
|
+
const tsNode = parserServices.esTreeNodeToTSNodeMap.get(param);
|
|
89
|
+
const type = typeChecker.getTypeAtLocation(tsNode);
|
|
97
90
|
if (!type.symbol)
|
|
98
91
|
continue;
|
|
99
|
-
|
|
92
|
+
const isClass = type.symbol.flags === SymbolFlags.Class;
|
|
100
93
|
if (!isClass)
|
|
101
94
|
continue;
|
|
102
95
|
context.report({
|
|
@@ -109,3 +102,4 @@ var validateConstructorParameterProperty = function (_a) {
|
|
|
109
102
|
});
|
|
110
103
|
}
|
|
111
104
|
};
|
|
105
|
+
//# sourceMappingURL=no-public-class-fields.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-public-class-fields.mjs","sourceRoot":"","sources":["../src/no-public-class-fields.mts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { AST_NODE_TYPES, ESLintUtils, } from "@typescript-eslint/utils";
|
|
2
|
+
import { isConstructType } from "./utils/typeCheck.mjs";
|
|
3
|
+
export const noVariableConstructId = ESLintUtils.RuleCreator.withoutDocs({
|
|
4
|
+
meta: {
|
|
5
|
+
type: "problem",
|
|
6
|
+
docs: {
|
|
7
|
+
description: `Enforce using literal strings for Construct ID.`,
|
|
8
|
+
},
|
|
9
|
+
messages: {
|
|
10
|
+
noVariableConstructId: "Shouldn't use a parameter as a Construct ID.",
|
|
11
|
+
},
|
|
12
|
+
schema: [],
|
|
13
|
+
},
|
|
14
|
+
defaultOptions: [],
|
|
15
|
+
create(context) {
|
|
16
|
+
const parserServices = ESLintUtils.getParserServices(context);
|
|
17
|
+
const typeChecker = parserServices.program.getTypeChecker();
|
|
18
|
+
return {
|
|
19
|
+
NewExpression(node) {
|
|
20
|
+
const type = typeChecker.getTypeAtLocation(parserServices.esTreeNodeToTSNodeMap.get(node));
|
|
21
|
+
if (!isConstructType(type)) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
if (node.arguments.length < 2)
|
|
25
|
+
return;
|
|
26
|
+
validateConstructId(node, context, node);
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
const validateConstructId = (node, context, expression) => {
|
|
32
|
+
if (expression.arguments.length < 2 || isInsideLoop(node)) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const secondArg = expression.arguments[1];
|
|
36
|
+
if (secondArg.type === AST_NODE_TYPES.Literal &&
|
|
37
|
+
typeof secondArg.value === "string") {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (secondArg.type === AST_NODE_TYPES.TemplateLiteral &&
|
|
41
|
+
!secondArg.expressions.length) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
context.report({
|
|
45
|
+
node,
|
|
46
|
+
messageId: "noVariableConstructId",
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
const isInsideLoop = (node) => {
|
|
50
|
+
let current = node.parent;
|
|
51
|
+
while (current) {
|
|
52
|
+
if (current.type === AST_NODE_TYPES.ForStatement ||
|
|
53
|
+
current.type === AST_NODE_TYPES.ForInStatement ||
|
|
54
|
+
current.type === AST_NODE_TYPES.ForOfStatement ||
|
|
55
|
+
current.type === AST_NODE_TYPES.WhileStatement ||
|
|
56
|
+
current.type === AST_NODE_TYPES.DoWhileStatement) {
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
current = current.parent;
|
|
60
|
+
}
|
|
61
|
+
return false;
|
|
62
|
+
};
|
|
63
|
+
//# sourceMappingURL=no-variable-construct-id.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-variable-construct-id.mjs","sourceRoot":"","sources":["../src/no-variable-construct-id.mts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,WAAW,GAGZ,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AASxD,MAAM,CAAC,MAAM,qBAAqB,GAAG,WAAW,CAAC,WAAW,CAAC,WAAW,CAAC;IACvE,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EAAE,iDAAiD;SAC/D;QACD,QAAQ,EAAE;YACR,qBAAqB,EAAE,8CAA8C;SACtE;QACD,MAAM,EAAE,EAAE;KACX;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACZ,MAAM,cAAc,GAAG,WAAW,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAC9D,MAAM,WAAW,GAAG,cAAc,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;QAE5D,OAAO;YACL,aAAa,CAAC,IAAI;gBAChB,MAAM,IAAI,GAAG,WAAW,CAAC,iBAAiB,CACxC,cAAc,CAAC,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,CAC/C,CAAC;gBACF,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC3B,OAAO;gBACT,CAAC;gBAED,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC;oBAAE,OAAO;gBAEtC,mBAAmB,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;YAC3C,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC;AAKH,MAAM,mBAAmB,GAAG,CAC1B,IAAmB,EACnB,OAAgB,EAChB,UAAkC,EAClC,EAAE;IACF,IAAI,UAAU,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1D,OAAO;IACT,CAAC;IAGD,MAAM,SAAS,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAG1C,IACE,SAAS,CAAC,IAAI,KAAK,cAAc,CAAC,OAAO;QACzC,OAAO,SAAS,CAAC,KAAK,KAAK,QAAQ,EACnC,CAAC;QACD,OAAO;IACT,CAAC;IAGD,IACE,SAAS,CAAC,IAAI,KAAK,cAAc,CAAC,eAAe;QACjD,CAAC,SAAS,CAAC,WAAW,CAAC,MAAM,EAC7B,CAAC;QACD,OAAO;IACT,CAAC;IAED,OAAO,CAAC,MAAM,CAAC;QACb,IAAI;QACJ,SAAS,EAAE,uBAAuB;KACnC,CAAC,CAAC;AACL,CAAC,CAAC;AAKF,MAAM,YAAY,GAAG,CAAC,IAAmB,EAAW,EAAE;IACpD,IAAI,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC;IAC1B,OAAO,OAAO,EAAE,CAAC;QACf,IACE,OAAO,CAAC,IAAI,KAAK,cAAc,CAAC,YAAY;YAC5C,OAAO,CAAC,IAAI,KAAK,cAAc,CAAC,cAAc;YAC9C,OAAO,CAAC,IAAI,KAAK,cAAc,CAAC,cAAc;YAC9C,OAAO,CAAC,IAAI,KAAK,cAAc,CAAC,cAAc;YAC9C,OAAO,CAAC,IAAI,KAAK,cAAc,CAAC,gBAAgB,EAChD,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAC3B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC,CAAC"}
|
|
@@ -1,40 +1,11 @@
|
|
|
1
|
+
import { AST_NODE_TYPES, ESLintUtils, } from "@typescript-eslint/utils";
|
|
1
2
|
import { toPascalCase } from "./utils/convertString.mjs";
|
|
2
|
-
|
|
3
|
+
import { isConstructOrStackType } from "./utils/typeCheck.mjs";
|
|
4
|
+
const QUOTE_TYPE = {
|
|
3
5
|
SINGLE: "'",
|
|
4
6
|
DOUBLE: '"',
|
|
5
7
|
};
|
|
6
|
-
|
|
7
|
-
* check if the string is PascalCase
|
|
8
|
-
* @param str - The string to check
|
|
9
|
-
* @returns true if the string is PascalCase, false otherwise
|
|
10
|
-
*/
|
|
11
|
-
var isPascalCase = function (str) {
|
|
12
|
-
return /^[A-Z][a-zA-Z0-9]*$/.test(str);
|
|
13
|
-
};
|
|
14
|
-
var validateConstructId = function (node, context, args) {
|
|
15
|
-
var _a;
|
|
16
|
-
if (args.length < 2)
|
|
17
|
-
return;
|
|
18
|
-
// NOTE: Treat the second argument as ID
|
|
19
|
-
var secondArg = args[1];
|
|
20
|
-
if (secondArg.type !== "Literal" || typeof secondArg.value !== "string") {
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
var quote = ((_a = secondArg.raw) === null || _a === void 0 ? void 0 : _a.startsWith('"'))
|
|
24
|
-
? QUOTE_TYPE.DOUBLE
|
|
25
|
-
: QUOTE_TYPE.SINGLE;
|
|
26
|
-
if (!isPascalCase(secondArg.value)) {
|
|
27
|
-
context.report({
|
|
28
|
-
node: node,
|
|
29
|
-
messageId: "pascalCaseConstructId",
|
|
30
|
-
fix: function (fixer) {
|
|
31
|
-
var pascalCaseValue = toPascalCase(secondArg.value);
|
|
32
|
-
return fixer.replaceText(secondArg, "".concat(quote).concat(pascalCaseValue).concat(quote));
|
|
33
|
-
},
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
export var pascalCaseConstructId = {
|
|
8
|
+
export const pascalCaseConstructId = ESLintUtils.RuleCreator.withoutDocs({
|
|
38
9
|
meta: {
|
|
39
10
|
type: "problem",
|
|
40
11
|
docs: {
|
|
@@ -46,24 +17,46 @@ export var pascalCaseConstructId = {
|
|
|
46
17
|
schema: [],
|
|
47
18
|
fixable: "code",
|
|
48
19
|
},
|
|
49
|
-
|
|
20
|
+
defaultOptions: [],
|
|
21
|
+
create(context) {
|
|
22
|
+
const parserServices = ESLintUtils.getParserServices(context);
|
|
23
|
+
const typeChecker = parserServices.program.getTypeChecker();
|
|
50
24
|
return {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
validateConstructId(node, context, node.expression.arguments);
|
|
55
|
-
},
|
|
56
|
-
VariableDeclaration: function (node) {
|
|
57
|
-
var _a;
|
|
58
|
-
if (!node.declarations.length)
|
|
25
|
+
NewExpression(node) {
|
|
26
|
+
const type = typeChecker.getTypeAtLocation(parserServices.esTreeNodeToTSNodeMap.get(node));
|
|
27
|
+
if (!isConstructOrStackType(type)) {
|
|
59
28
|
return;
|
|
60
|
-
for (var _i = 0, _b = node.declarations; _i < _b.length; _i++) {
|
|
61
|
-
var declaration = _b[_i];
|
|
62
|
-
if (((_a = declaration.init) === null || _a === void 0 ? void 0 : _a.type) !== "NewExpression")
|
|
63
|
-
return;
|
|
64
|
-
validateConstructId(node, context, declaration.init.arguments);
|
|
65
29
|
}
|
|
30
|
+
if (node.arguments.length < 2)
|
|
31
|
+
return;
|
|
32
|
+
validateConstructId(node, context, node);
|
|
66
33
|
},
|
|
67
34
|
};
|
|
68
35
|
},
|
|
36
|
+
});
|
|
37
|
+
const isPascalCase = (str) => {
|
|
38
|
+
return /^[A-Z][a-zA-Z0-9]*$/.test(str);
|
|
39
|
+
};
|
|
40
|
+
const validateConstructId = (node, context, expression) => {
|
|
41
|
+
if (expression.arguments.length < 2)
|
|
42
|
+
return;
|
|
43
|
+
const secondArg = expression.arguments[1];
|
|
44
|
+
if (secondArg.type !== AST_NODE_TYPES.Literal ||
|
|
45
|
+
typeof secondArg.value !== "string") {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const quote = secondArg.raw?.startsWith('"')
|
|
49
|
+
? QUOTE_TYPE.DOUBLE
|
|
50
|
+
: QUOTE_TYPE.SINGLE;
|
|
51
|
+
if (!isPascalCase(secondArg.value)) {
|
|
52
|
+
context.report({
|
|
53
|
+
node,
|
|
54
|
+
messageId: "pascalCaseConstructId",
|
|
55
|
+
fix: (fixer) => {
|
|
56
|
+
const pascalCaseValue = toPascalCase(secondArg.value);
|
|
57
|
+
return fixer.replaceText(secondArg, `${quote}${pascalCaseValue}${quote}`);
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
}
|
|
69
61
|
};
|
|
62
|
+
//# sourceMappingURL=pascal-case-construct-id.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pascal-case-construct-id.mjs","sourceRoot":"","sources":["../src/pascal-case-construct-id.mts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,WAAW,GAGZ,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,MAAM,UAAU,GAAG;IACjB,MAAM,EAAE,GAAG;IACX,MAAM,EAAE,GAAG;CACH,CAAC;AAaX,MAAM,CAAC,MAAM,qBAAqB,GAAG,WAAW,CAAC,WAAW,CAAC,WAAW,CAAC;IACvE,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EAAE,sCAAsC;SACpD;QACD,QAAQ,EAAE;YACR,qBAAqB,EAAE,kCAAkC;SAC1D;QACD,MAAM,EAAE,EAAE;QACV,OAAO,EAAE,MAAM;KAChB;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACZ,MAAM,cAAc,GAAG,WAAW,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAC9D,MAAM,WAAW,GAAG,cAAc,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;QAC5D,OAAO;YACL,aAAa,CAAC,IAAI;gBAChB,MAAM,IAAI,GAAG,WAAW,CAAC,iBAAiB,CACxC,cAAc,CAAC,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,CAC/C,CAAC;gBACF,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,EAAE,CAAC;oBAClC,OAAO;gBACT,CAAC;gBAED,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC;oBAAE,OAAO;gBAEtC,mBAAmB,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;YAC3C,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC;AAOH,MAAM,YAAY,GAAG,CAAC,GAAW,EAAE,EAAE;IACnC,OAAO,qBAAqB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzC,CAAC,CAAC;AAKF,MAAM,mBAAmB,GAAG,CAC1B,IAAmB,EACnB,OAAgB,EAChB,UAAkC,EAClC,EAAE;IACF,IAAI,UAAU,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO;IAG5C,MAAM,SAAS,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAC1C,IACE,SAAS,CAAC,IAAI,KAAK,cAAc,CAAC,OAAO;QACzC,OAAO,SAAS,CAAC,KAAK,KAAK,QAAQ,EACnC,CAAC;QACD,OAAO;IACT,CAAC;IAED,MAAM,KAAK,GAAc,SAAS,CAAC,GAAG,EAAE,UAAU,CAAC,GAAG,CAAC;QACrD,CAAC,CAAC,UAAU,CAAC,MAAM;QACnB,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC;IAEtB,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;QACnC,OAAO,CAAC,MAAM,CAAC;YACb,IAAI;YACJ,SAAS,EAAE,uBAAuB;YAClC,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE;gBACb,MAAM,eAAe,GAAG,YAAY,CAAC,SAAS,CAAC,KAAe,CAAC,CAAC;gBAChE,OAAO,KAAK,CAAC,WAAW,CACtB,SAAS,EACT,GAAG,KAAK,GAAG,eAAe,GAAG,KAAK,EAAE,CACrC,CAAC;YACJ,CAAC;SACF,CAAC,CAAC;IACL,CAAC;AACH,CAAC,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { AST_NODE_TYPES, ESLintUtils } from "@typescript-eslint/utils";
|
|
2
|
+
import { isConstructType } from "./utils/typeCheck.mjs";
|
|
3
|
+
export const requirePassingThis = ESLintUtils.RuleCreator.withoutDocs({
|
|
4
|
+
meta: {
|
|
5
|
+
type: "problem",
|
|
6
|
+
docs: {
|
|
7
|
+
description: "Require passing `this` in a constructor.",
|
|
8
|
+
},
|
|
9
|
+
messages: {
|
|
10
|
+
requirePassingThis: "Require passing `this` in a constructor.",
|
|
11
|
+
},
|
|
12
|
+
schema: [],
|
|
13
|
+
fixable: "code",
|
|
14
|
+
},
|
|
15
|
+
defaultOptions: [],
|
|
16
|
+
create(context) {
|
|
17
|
+
const parserServices = ESLintUtils.getParserServices(context);
|
|
18
|
+
const typeChecker = parserServices.program.getTypeChecker();
|
|
19
|
+
return {
|
|
20
|
+
NewExpression(node) {
|
|
21
|
+
const type = typeChecker.getTypeAtLocation(parserServices.esTreeNodeToTSNodeMap.get(node));
|
|
22
|
+
if (!isConstructType(type) || !node.arguments.length) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const argument = node.arguments[0];
|
|
26
|
+
if (argument.type !== AST_NODE_TYPES.ThisExpression) {
|
|
27
|
+
context.report({
|
|
28
|
+
node,
|
|
29
|
+
messageId: "requirePassingThis",
|
|
30
|
+
fix: (fixer) => {
|
|
31
|
+
return fixer.replaceText(argument, "this");
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
//# sourceMappingURL=require-passing-this.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"require-passing-this.mjs","sourceRoot":"","sources":["../src/require-passing-this.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvE,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAQxD,MAAM,CAAC,MAAM,kBAAkB,GAAG,WAAW,CAAC,WAAW,CAAC,WAAW,CAAC;IACpE,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EAAE,0CAA0C;SACxD;QACD,QAAQ,EAAE;YACR,kBAAkB,EAAE,0CAA0C;SAC/D;QACD,MAAM,EAAE,EAAE;QACV,OAAO,EAAE,MAAM;KAChB;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACZ,MAAM,cAAc,GAAG,WAAW,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAC9D,MAAM,WAAW,GAAG,cAAc,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;QAC5D,OAAO;YACL,aAAa,CAAC,IAAI;gBAChB,MAAM,IAAI,GAAG,WAAW,CAAC,iBAAiB,CACxC,cAAc,CAAC,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,CAC/C,CAAC;gBAEF,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;oBACrD,OAAO;gBACT,CAAC;gBAED,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;gBAEnC,IAAI,QAAQ,CAAC,IAAI,KAAK,cAAc,CAAC,cAAc,EAAE,CAAC;oBACpD,OAAO,CAAC,MAAM,CAAC;wBACb,IAAI;wBACJ,SAAS,EAAE,oBAAoB;wBAC/B,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE;4BACb,OAAO,KAAK,CAAC,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;wBAC7C,CAAC;qBACF,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const toPascalCase: (str: string) => string;
|
|
@@ -1,18 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
* Convert a string to PascalCase
|
|
3
|
-
* @param str - The string to convert
|
|
4
|
-
* @returns The PascalCase string
|
|
5
|
-
*/
|
|
6
|
-
export var toPascalCase = function (str) {
|
|
1
|
+
export const toPascalCase = (str) => {
|
|
7
2
|
return str
|
|
8
3
|
.split(/[-_\s]/)
|
|
9
|
-
.map(
|
|
10
|
-
// Consider camelCase, split by uppercase letters
|
|
4
|
+
.map((word) => {
|
|
11
5
|
return word
|
|
12
6
|
.replace(/([A-Z])/g, " $1")
|
|
13
7
|
.split(/\s+/)
|
|
14
|
-
.map(
|
|
8
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())
|
|
15
9
|
.join("");
|
|
16
10
|
})
|
|
17
11
|
.join("");
|
|
18
12
|
};
|
|
13
|
+
//# sourceMappingURL=convertString.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convertString.mjs","sourceRoot":"","sources":["../../src/utils/convertString.mts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAW,EAAU,EAAE;IAClD,OAAO,GAAG;SACP,KAAK,CAAC,QAAQ,CAAC;SACf,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QAEZ,OAAO,IAAI;aACR,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC;aAC1B,KAAK,CAAC,KAAK,CAAC;aACZ,GAAG,CACF,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CACrE;aACA,IAAI,CAAC,EAAE,CAAC,CAAC;IACd,CAAC,CAAC;SACD,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const isConstructOrStackType = (type) => {
|
|
2
|
+
return isTargetSuperClassType(type, ["Construct", "Stack"]);
|
|
3
|
+
};
|
|
4
|
+
export const isConstructType = (type) => {
|
|
5
|
+
return isTargetSuperClassType(type, ["Construct"]);
|
|
6
|
+
};
|
|
7
|
+
const isTargetSuperClassType = (type, targetSuperClasses) => {
|
|
8
|
+
if (!type.symbol)
|
|
9
|
+
return false;
|
|
10
|
+
if (targetSuperClasses.some((suffix) => type.symbol.name.endsWith(suffix))) {
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
const baseTypes = type.getBaseTypes() || [];
|
|
14
|
+
return baseTypes.some((baseType) => isConstructOrStackType(baseType));
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=typeCheck.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typeCheck.mjs","sourceRoot":"","sources":["../../src/utils/typeCheck.mts"],"names":[],"mappings":"AASA,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,IAAU,EAAW,EAAE;IAC5D,OAAO,sBAAsB,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC;AAC9D,CAAC,CAAC;AAOF,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,IAAU,EAAW,EAAE;IACrD,OAAO,sBAAsB,CAAC,IAAI,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;AACrD,CAAC,CAAC;AAQF,MAAM,sBAAsB,GAAG,CAC7B,IAAU,EACV,kBAAoC,EAC3B,EAAE;IACX,IAAI,CAAC,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAG/B,IAAI,kBAAkB,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;QAC3E,OAAO,IAAI,CAAC;IACd,CAAC;IAGD,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,EAAE,IAAI,EAAE,CAAC;IAC5C,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,sBAAsB,CAAC,QAAQ,CAAC,CAAC,CAAC;AACxE,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-cdk-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "eslint plugin for AWS CDK projects",
|
|
5
5
|
"main": "dist/index.mjs",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"build": "rm -rf dist && tsc
|
|
8
|
+
"build": "rm -rf dist && tsc -p tsconfig.build.json",
|
|
9
9
|
"test": "vitest --run",
|
|
10
10
|
"lint": "eslint --fix --config eslint.config.mjs",
|
|
11
11
|
"release:minor": "standard-version --release-as minor",
|
|
@@ -36,7 +36,10 @@
|
|
|
36
36
|
"files": [
|
|
37
37
|
"dist",
|
|
38
38
|
"README.md",
|
|
39
|
-
"LICENSE"
|
|
39
|
+
"LICENSE",
|
|
40
|
+
"CONTRIBUTING.md",
|
|
41
|
+
"VERSIONING_POLICY.md",
|
|
42
|
+
"assets"
|
|
40
43
|
],
|
|
41
44
|
"keywords": [
|
|
42
45
|
"eslint",
|