@simplysm/eslint-plugin 7.0.25 → 7.0.39
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/.eslintrc.cjs +1 -1
- package/package.json +7 -2
- package/src/configs/angular-template.cjs +10 -0
- package/src/configs/angular.cjs +5 -0
- package/src/configs/base.cjs +7 -1
- package/src/configs/typescript.cjs +21 -2
- package/src/index.cjs +9 -4
- package/src/rules/ng-template-no-todo-comments.cjs +45 -0
- package/src/rules/ts-no-self-entry-import.cjs +64 -0
- package/src/rules/ts-no-throw-not-implement-error.cjs +73 -0
package/.eslintrc.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
module.exports = {};
|
|
1
|
+
module.exports = {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simplysm/eslint-plugin",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.39",
|
|
4
4
|
"description": "심플리즘 패키지 - ESLINT 플러그인",
|
|
5
5
|
"author": "김석래",
|
|
6
6
|
"repository": {
|
|
@@ -18,7 +18,12 @@
|
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"eslint": "^8.7.0",
|
|
20
20
|
"@typescript-eslint/parser": "^5.10.1",
|
|
21
|
-
"@typescript-eslint/eslint-plugin": "^5.10.1"
|
|
21
|
+
"@typescript-eslint/eslint-plugin": "^5.10.1",
|
|
22
|
+
"@angular-eslint/eslint-plugin": "^13.0.1",
|
|
23
|
+
"@angular-eslint/eslint-plugin-template": "^13.0.1",
|
|
24
|
+
"@angular-eslint/template-parser": "^13.0.1",
|
|
25
|
+
"@typescript-eslint/experimental-utils": "^5.10.2",
|
|
26
|
+
"eslint-module-utils": "^2.7.3"
|
|
22
27
|
},
|
|
23
28
|
"devDependencies": {},
|
|
24
29
|
"peerDependencies": {}
|
package/src/configs/base.cjs
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
module.exports = {
|
|
2
|
+
env: {
|
|
3
|
+
node: true,
|
|
4
|
+
es2020: true
|
|
5
|
+
},
|
|
2
6
|
rules: {
|
|
3
7
|
"require-await": ["error"],
|
|
4
8
|
"quotes": ["error"],
|
|
@@ -6,6 +10,8 @@ module.exports = {
|
|
|
6
10
|
"no-shadow": ["error"],
|
|
7
11
|
"no-duplicate-imports": ["error"],
|
|
8
12
|
"no-unused-expressions": ["error"],
|
|
9
|
-
"no-unused-vars": ["error"]
|
|
13
|
+
"no-unused-vars": ["error"],
|
|
14
|
+
"no-undef": ["error"],
|
|
15
|
+
"comma-dangle": ["error"]
|
|
10
16
|
}
|
|
11
17
|
};
|
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
module.exports = {
|
|
2
2
|
parser: "@typescript-eslint/parser",
|
|
3
|
-
plugins: [
|
|
3
|
+
plugins: [
|
|
4
|
+
"@typescript-eslint",
|
|
5
|
+
"@simplysm"
|
|
6
|
+
],
|
|
7
|
+
// extends: [
|
|
8
|
+
// "plugin:@typescript-eslint/all"
|
|
9
|
+
// ],
|
|
4
10
|
rules: {
|
|
11
|
+
// 심플리즘
|
|
12
|
+
"@simplysm/ts-no-throw-not-implement-error": "warn",
|
|
13
|
+
"@simplysm/ts-no-self-entry-import": "error",
|
|
14
|
+
|
|
15
|
+
// 타입스크립트
|
|
5
16
|
"@typescript-eslint/explicit-member-accessibility": ["error"],
|
|
6
17
|
"@typescript-eslint/require-await": ["error"],
|
|
7
18
|
"@typescript-eslint/await-thenable": ["error"],
|
|
@@ -25,6 +36,14 @@ module.exports = {
|
|
|
25
36
|
allowConciseArrowFunctionExpressionsStartingWithVoid: true
|
|
26
37
|
}],
|
|
27
38
|
"@typescript-eslint/no-unused-expressions": ["error"],
|
|
28
|
-
"@typescript-eslint/no-unused-vars": ["
|
|
39
|
+
"@typescript-eslint/no-unused-vars": ["warn", { args: "none" }],
|
|
40
|
+
"@typescript-eslint/strict-boolean-expressions": ["error", {
|
|
41
|
+
allowNullableBoolean: true,
|
|
42
|
+
allowNullableObject: true
|
|
43
|
+
}],
|
|
44
|
+
"@typescript-eslint/explicit-module-boundary-types": ["error", { allowArgumentsExplicitlyTypedAsAny: true }],
|
|
45
|
+
"@typescript-eslint/return-await": ["error", "always"],
|
|
46
|
+
"@typescript-eslint/no-floating-promises": ["error"],
|
|
47
|
+
"@typescript-eslint/comma-dangle": ["error"]
|
|
29
48
|
}
|
|
30
49
|
};
|
package/src/index.cjs
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
module.exports = {
|
|
2
2
|
configs: {
|
|
3
3
|
"base": require("./configs/base.cjs"),
|
|
4
|
-
"typescript": require("./configs/typescript.cjs")
|
|
4
|
+
"typescript": require("./configs/typescript.cjs"),
|
|
5
|
+
"angular": require("./configs/angular.cjs"),
|
|
6
|
+
"angular-template": require("./configs/angular-template.cjs")
|
|
5
7
|
},
|
|
6
|
-
rules: {
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
rules: {
|
|
9
|
+
"ts-no-self-entry-import": require("./rules/ts-no-self-entry-import.cjs"),
|
|
10
|
+
"ts-no-throw-not-implement-error": require("./rules/ts-no-throw-not-implement-error.cjs"),
|
|
11
|
+
"ng-template-no-todo-comments": require("./rules/ng-template-no-todo-comments.cjs")
|
|
12
|
+
}
|
|
13
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
meta: {
|
|
3
|
+
type: "suggestion",
|
|
4
|
+
docs: {
|
|
5
|
+
description: "'TODO' 주석 경고"
|
|
6
|
+
},
|
|
7
|
+
|
|
8
|
+
schema: []
|
|
9
|
+
},
|
|
10
|
+
|
|
11
|
+
create: (context) => {
|
|
12
|
+
// const parserServices = context.parserServices;
|
|
13
|
+
return {
|
|
14
|
+
Program(node) {
|
|
15
|
+
if (node.value) {
|
|
16
|
+
const comments = node.value.match(/<!--(((?!-->)[\s\S])*)-->/g);
|
|
17
|
+
if (!comments) return;
|
|
18
|
+
|
|
19
|
+
let cursor = 0;
|
|
20
|
+
for (const comment of comments) {
|
|
21
|
+
if (!comment.includes("TODO:")) continue;
|
|
22
|
+
|
|
23
|
+
const index = node.value.slice(cursor).indexOf(comment) + cursor;
|
|
24
|
+
const line = node.value.slice(0, index).split("\n").length;
|
|
25
|
+
const column = index - node.value.slice(0, index).lastIndexOf("\n") - 1;
|
|
26
|
+
|
|
27
|
+
const endIndex = index + comment.length;
|
|
28
|
+
const endLine = node.value.slice(0, endIndex).split("\n").length;
|
|
29
|
+
const endColumn = endIndex - node.value.slice(0, endIndex).lastIndexOf("\n") - 1;
|
|
30
|
+
|
|
31
|
+
cursor += index;
|
|
32
|
+
|
|
33
|
+
context.report({
|
|
34
|
+
loc: {
|
|
35
|
+
start: { line, column },
|
|
36
|
+
end: { line: endLine, column: endColumn }
|
|
37
|
+
},
|
|
38
|
+
message: comment.match(/<!--(((?!-->)[\s\S])*)-->/)[1].trim()
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
const resolve = require("eslint-module-utils/resolve").default;
|
|
2
|
+
const path = require("path");
|
|
3
|
+
|
|
4
|
+
module.exports = {
|
|
5
|
+
meta: {
|
|
6
|
+
type: "problem",
|
|
7
|
+
docs: {
|
|
8
|
+
description: "동일 패키지 내의 index.ts 파일 import 금지"
|
|
9
|
+
},
|
|
10
|
+
|
|
11
|
+
schema: []
|
|
12
|
+
},
|
|
13
|
+
create: (context) => {
|
|
14
|
+
const filePath = context.getFilename();
|
|
15
|
+
const importMap = new Map();
|
|
16
|
+
|
|
17
|
+
function append(requirePath, node) {
|
|
18
|
+
if (filePath !== "<text>" && (requirePath.endsWith(".") || requirePath.endsWith("/"))) {
|
|
19
|
+
const resolvedPath = (resolve(requirePath, context) || requirePath).toLowerCase();
|
|
20
|
+
if (resolvedPath) {
|
|
21
|
+
if (importMap.has(resolvedPath)) {
|
|
22
|
+
importMap.get(resolvedPath).push(node);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
importMap.set(resolvedPath, [node]);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
"ImportDeclaration": (node) => {
|
|
33
|
+
append(node.source.value, node);
|
|
34
|
+
},
|
|
35
|
+
"CallExpression": (node) => {
|
|
36
|
+
if (
|
|
37
|
+
node
|
|
38
|
+
&& node.callee
|
|
39
|
+
&& node.callee.type === "Identifier"
|
|
40
|
+
&& node.callee.name === "require"
|
|
41
|
+
&& node.arguments.length === 1
|
|
42
|
+
&& node.arguments[0].type === "Literal"
|
|
43
|
+
&& typeof node.arguments[0].value === "string"
|
|
44
|
+
) {
|
|
45
|
+
append(node.arguments[0].value, node);
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"Program:exit": () => {
|
|
49
|
+
const rootFileNames = context.parserServices.program.getRootFileNames()
|
|
50
|
+
.map((item) => path.normalize(item).toLowerCase());
|
|
51
|
+
for (const rootFileName of rootFileNames) {
|
|
52
|
+
if (importMap.has(rootFileName)) {
|
|
53
|
+
for (const node of importMap.get(rootFileName)) {
|
|
54
|
+
context.report({
|
|
55
|
+
node,
|
|
56
|
+
message: "동일 패키지상의 index.ts 파일을 import 하고 있습니다."
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
const { AST_NODE_TYPES } = require("@typescript-eslint/experimental-utils");
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
meta: {
|
|
5
|
+
type: "suggestion",
|
|
6
|
+
docs: {
|
|
7
|
+
description: "'NotImplementError' 사용 경고"
|
|
8
|
+
},
|
|
9
|
+
|
|
10
|
+
schema: []
|
|
11
|
+
},
|
|
12
|
+
create: (context) => {
|
|
13
|
+
const parserServices = context.parserServices;
|
|
14
|
+
const program = parserServices.program;
|
|
15
|
+
const checker = program.getTypeChecker();
|
|
16
|
+
|
|
17
|
+
function tryGetThrowArgumentType(node) {
|
|
18
|
+
switch (node.type) {
|
|
19
|
+
case AST_NODE_TYPES.Identifier:
|
|
20
|
+
case AST_NODE_TYPES.CallExpression:
|
|
21
|
+
case AST_NODE_TYPES.NewExpression:
|
|
22
|
+
case AST_NODE_TYPES.MemberExpression: {
|
|
23
|
+
const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node);
|
|
24
|
+
return checker.getTypeAtLocation(tsNode);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
case AST_NODE_TYPES.AssignmentExpression:
|
|
28
|
+
return tryGetThrowArgumentType(node.right);
|
|
29
|
+
|
|
30
|
+
case AST_NODE_TYPES.SequenceExpression:
|
|
31
|
+
return tryGetThrowArgumentType(node.expressions[node.expressions.length - 1]);
|
|
32
|
+
|
|
33
|
+
case AST_NODE_TYPES.LogicalExpression: {
|
|
34
|
+
const left = tryGetThrowArgumentType(node.left);
|
|
35
|
+
return left === undefined ? tryGetThrowArgumentType(node.right) : left;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
case AST_NODE_TYPES.ConditionalExpression: {
|
|
39
|
+
const consequent = tryGetThrowArgumentType(node.consequent);
|
|
40
|
+
return consequent === undefined ? tryGetThrowArgumentType(node.alternate) : consequent;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
default:
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function checkThrowArgument(node) {
|
|
49
|
+
if (
|
|
50
|
+
node.type === AST_NODE_TYPES.AwaitExpression
|
|
51
|
+
|| node.type === AST_NODE_TYPES.YieldExpression
|
|
52
|
+
) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const type = tryGetThrowArgumentType(node);
|
|
57
|
+
if (type && type.getSymbol() && type.getSymbol().getName() === "NotImplementError") {
|
|
58
|
+
context.report({
|
|
59
|
+
node,
|
|
60
|
+
message: node.arguments.value || "구현되어있지 않습니다" //"'NotImplementError'를 'throw'하고 있습니다."
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
ThrowStatement(node) {
|
|
67
|
+
if (node.argument) {
|
|
68
|
+
checkThrowArgument(node.argument);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
};
|