eslint-plugin-better-codes 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/README.md +57 -0
- package/index.js +9 -0
- package/libs/function-with-try-catch-code.js +86 -0
- package/libs/no-commented-code.js +166 -0
- package/package.json +15 -0
package/README.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# eslint-plugin-better-codes
|
|
2
|
+
|
|
3
|
+
<!-- <p align="center">
|
|
4
|
+
<img src="./icon.svg" alt="eslint-plugin-better-codes icon" width="120" />
|
|
5
|
+
</p> -->
|
|
6
|
+
|
|
7
|
+
简体中文
|
|
8
|
+
|
|
9
|
+
## 简介
|
|
10
|
+
|
|
11
|
+
`eslint-plugin-better-codes` 是一组自定义的 ESLint 插件规则集合,其中包含用于检测并禁止被注释掉的代码的规则 `eslint-no-commented-code`。帮助团队保持代码库清洁,避免大量被注释的冗余代码。
|
|
12
|
+
|
|
13
|
+
## 安装
|
|
14
|
+
|
|
15
|
+
使用 npm:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install --save-dev eslint-plugin-better-codes
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
或使用 yarn:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
yarn add -D eslint-plugin-better-codes
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## 使用方式
|
|
28
|
+
|
|
29
|
+
在你的 ESLint 配置文件中启用插件并打开规则。例如 `.eslintrc.js`:
|
|
30
|
+
|
|
31
|
+
```javascript
|
|
32
|
+
module.exports = {
|
|
33
|
+
plugins: ["better-codes"],
|
|
34
|
+
rules: {
|
|
35
|
+
"better-codes/no-commented-code": "error",
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
规则名:`no-commented-code`(导出于 `index.js` 中)。
|
|
41
|
+
|
|
42
|
+
## 主要功能
|
|
43
|
+
|
|
44
|
+
### no-commented-code
|
|
45
|
+
|
|
46
|
+
禁止提交注释掉的代码:
|
|
47
|
+
|
|
48
|
+
- 对于单行注释:累计行数大于等于minLines时报错。对于第一个字符为中文、大写英文字母、数字,不进行校验。如果最后面包含ignore-eslint,不进行校验(最多可以忽略minLines - 1次)
|
|
49
|
+
- 对于多行注释:累计行数大于等于minLines时报错,空格行、只包含\*的行、空行不计数。如果内容包含@param、@returns(函数注释),@D(d)escription(文件头注释),@C(c)omment(块状功能注释)不进行校验
|
|
50
|
+
|
|
51
|
+
### function-with-try-catch
|
|
52
|
+
|
|
53
|
+
强制函数必须包含 try-catch 语句块
|
|
54
|
+
|
|
55
|
+
## 许可证
|
|
56
|
+
|
|
57
|
+
MIT
|
package/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
const noCommentedCode = require("./libs/no-commented-code.js");
|
|
2
|
+
const functionWithTryCatch = require("./libs/function-with-try-catch-code.js");
|
|
3
|
+
const plugin = {
|
|
4
|
+
rules: {
|
|
5
|
+
"no-commented-code": noCommentedCode,
|
|
6
|
+
"function-with-try-catch": functionWithTryCatch,
|
|
7
|
+
},
|
|
8
|
+
};
|
|
9
|
+
module.exports = plugin;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 检查函数体中是否包含 try...catch
|
|
3
|
+
* 对于有函数体且包含语句的函数,如果没有 try/catch 报警
|
|
4
|
+
*/
|
|
5
|
+
function containsTryStatement(node) {
|
|
6
|
+
let found = false;
|
|
7
|
+
const seen = new Set();
|
|
8
|
+
function traverse(n) {
|
|
9
|
+
if (!n || found) return;
|
|
10
|
+
if (seen.has(n)) return;
|
|
11
|
+
if (Array.isArray(n)) {
|
|
12
|
+
for (const item of n) {
|
|
13
|
+
traverse(item);
|
|
14
|
+
if (found) return;
|
|
15
|
+
}
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (typeof n !== "object") return;
|
|
19
|
+
seen.add(n);
|
|
20
|
+
if (n.type === "TryStatement") {
|
|
21
|
+
found = true;
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
for (const key of Object.keys(n)) {
|
|
25
|
+
if (found) break;
|
|
26
|
+
const child = n[key];
|
|
27
|
+
if (child && typeof child === "object") {
|
|
28
|
+
traverse(child);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
traverse(node);
|
|
33
|
+
return found;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
module.exports = {
|
|
37
|
+
meta: {
|
|
38
|
+
type: "suggestion",
|
|
39
|
+
docs: {
|
|
40
|
+
description: "提醒函数内部应包含 try...catch 以便处理异常",
|
|
41
|
+
category: "Best Practices",
|
|
42
|
+
recommended: false,
|
|
43
|
+
},
|
|
44
|
+
schema: [],
|
|
45
|
+
},
|
|
46
|
+
create(context) {
|
|
47
|
+
function reportIfMissingTry(node, name) {
|
|
48
|
+
// 箭头函数表达式且为表达式体,跳过
|
|
49
|
+
if (node.type === "ArrowFunctionExpression" && node.body && node.body.type !== "BlockStatement") {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const body = node.body;
|
|
53
|
+
if (!body || body.type !== "BlockStatement") return;
|
|
54
|
+
const stmts = body.body || [];
|
|
55
|
+
// 如果函数体为空或只有注释/空,则跳过
|
|
56
|
+
if (stmts.length === 0) return;
|
|
57
|
+
// 如果函数体中包含 TryStatement,说明已处理,跳过
|
|
58
|
+
if (containsTryStatement(body)) return;
|
|
59
|
+
context.report({
|
|
60
|
+
node,
|
|
61
|
+
message: `${name || '函数'} 未包含 try...catch,建议添加错误处理`,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
FunctionDeclaration(node) {
|
|
67
|
+
const name = node.id && node.id.name;
|
|
68
|
+
reportIfMissingTry(node, name);
|
|
69
|
+
},
|
|
70
|
+
FunctionExpression(node) {
|
|
71
|
+
const name = node.id && node.id.name;
|
|
72
|
+
reportIfMissingTry(node, name);
|
|
73
|
+
},
|
|
74
|
+
ArrowFunctionExpression(node) {
|
|
75
|
+
reportIfMissingTry(node, '箭头函数');
|
|
76
|
+
},
|
|
77
|
+
MethodDefinition(node) {
|
|
78
|
+
// 跳过 constructor/get/set
|
|
79
|
+
if (node.kind === 'constructor' || node.kind === 'get' || node.kind === 'set') return;
|
|
80
|
+
const key = node.key && (node.key.name || (node.key.value && String(node.key.value)));
|
|
81
|
+
if (node.value) reportIfMissingTry(node.value, key || '方法');
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 区分功能注释和代码注释
|
|
3
|
+
* @param {String} comment - 注释的内容
|
|
4
|
+
* @param {Boolean} isBlock - 是否为块注释
|
|
5
|
+
* @returns {Boolean} 是否为功能注释
|
|
6
|
+
*/
|
|
7
|
+
function isFunctionComment(comment, isBlock = false) {
|
|
8
|
+
try {
|
|
9
|
+
// 去除前后空格
|
|
10
|
+
comment = comment.trim();
|
|
11
|
+
// 取第一个字符
|
|
12
|
+
const firstStr = comment[0];
|
|
13
|
+
// 判断第一个字符是否为中文
|
|
14
|
+
const isChinese = /^[\u4e00-\u9fa5]+$/.test(firstStr);
|
|
15
|
+
// 判断第一个字符是否为大写英文字母
|
|
16
|
+
const isCapitalEnglish = /^[A-Z]+$/.test(firstStr);
|
|
17
|
+
// 判断第一个字符是否为数字
|
|
18
|
+
const isNum = /^[0-9]+$/.test(firstStr);
|
|
19
|
+
if (
|
|
20
|
+
isChinese ||
|
|
21
|
+
isCapitalEnglish ||
|
|
22
|
+
isFuncComment(comment, isBlock) ||
|
|
23
|
+
isNum
|
|
24
|
+
) {
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
} catch (error) {
|
|
28
|
+
console.error(error);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* 区分函数的功能注释
|
|
34
|
+
* 例如
|
|
35
|
+
* /**
|
|
36
|
+
* Function description
|
|
37
|
+
* @param {type} paramName - Parameter description
|
|
38
|
+
* @returns {type} Return description
|
|
39
|
+
*
|
|
40
|
+
* @param {String} comment - 注释的内容
|
|
41
|
+
* @param {Boolean} isBlock - 是否为块注释
|
|
42
|
+
* @returns {Boolean} 是否为函数的功能注释
|
|
43
|
+
*/
|
|
44
|
+
function isFuncComment(comment) {
|
|
45
|
+
if (
|
|
46
|
+
comment.includes("@param") ||
|
|
47
|
+
comment.includes("@returns") ||
|
|
48
|
+
comment.includes("@Description") ||
|
|
49
|
+
comment.includes("@description") ||
|
|
50
|
+
comment.includes("@comment") ||
|
|
51
|
+
comment.includes("@Comment")
|
|
52
|
+
) {
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
module.exports = {
|
|
58
|
+
meta: {
|
|
59
|
+
type: "problem",
|
|
60
|
+
docs: {
|
|
61
|
+
description: "禁止提交注释掉的代码块",
|
|
62
|
+
category: "Best Practices",
|
|
63
|
+
recommended: true,
|
|
64
|
+
},
|
|
65
|
+
schema: [
|
|
66
|
+
{
|
|
67
|
+
type: "object",
|
|
68
|
+
properties: {
|
|
69
|
+
minLines: {
|
|
70
|
+
type: "integer",
|
|
71
|
+
minimum: 1,
|
|
72
|
+
default: 3,
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
additionalProperties: false,
|
|
76
|
+
},
|
|
77
|
+
],
|
|
78
|
+
},
|
|
79
|
+
create(context) {
|
|
80
|
+
const sourceCode = context.getSourceCode();
|
|
81
|
+
const options = context.options[0] || {};
|
|
82
|
+
const minLines = options.minLines || 5;
|
|
83
|
+
let ignoredCount = 0; // 忽略次数
|
|
84
|
+
let singleLineCount = 0; // 单行注释行数 只计算最终实际校验生效的
|
|
85
|
+
return {
|
|
86
|
+
Program() {
|
|
87
|
+
const comments = sourceCode.getAllComments();
|
|
88
|
+
comments.forEach(comment => {
|
|
89
|
+
if (comment.loc) {
|
|
90
|
+
// 单行注释
|
|
91
|
+
if (comment.type === "Line") {
|
|
92
|
+
if (isFunctionComment(comment.value)) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
singleLineCount++;
|
|
96
|
+
|
|
97
|
+
const lines = comment.value.split("\n");
|
|
98
|
+
// 过滤空行,只计算有实际内容的行
|
|
99
|
+
const codeLines = lines.filter(line => {
|
|
100
|
+
const trimmed = line.trim();
|
|
101
|
+
return trimmed.length > 0;
|
|
102
|
+
});
|
|
103
|
+
const isIgnored = codeLines[0].endsWith("ignore-eslint"); // 因默认添加了ignore-eslint,进行忽略校验
|
|
104
|
+
if (isIgnored && ignoredCount < minLines) {
|
|
105
|
+
ignoredCount++;
|
|
106
|
+
singleLineCount--;
|
|
107
|
+
}
|
|
108
|
+
// 优先检查忽略次数:当忽略累计次数达到阈值时,优先提示并禁止继续忽略
|
|
109
|
+
if (ignoredCount >= minLines) {
|
|
110
|
+
context.report({
|
|
111
|
+
node: comment,
|
|
112
|
+
message: `总忽略次数大于等于${minLines}次,请删除或保留为有效代码`,
|
|
113
|
+
data: {
|
|
114
|
+
lines: ignoredCount,
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
// 其次检查单行注释总数
|
|
120
|
+
if (singleLineCount >= minLines) {
|
|
121
|
+
context.report({
|
|
122
|
+
node: comment,
|
|
123
|
+
message: `单行注释大于等于 ${minLines} 行代码,请删除或保留为有效代码`,
|
|
124
|
+
data: {
|
|
125
|
+
lines: singleLineCount,
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
// 如果注释块包含多行代码逻辑
|
|
131
|
+
if (codeLines.length >= minLines) {
|
|
132
|
+
context.report({
|
|
133
|
+
node: comment,
|
|
134
|
+
message: `注释掉了 ${codeLines.length} 行代码,请删除或保留为有效代码`,
|
|
135
|
+
data: {
|
|
136
|
+
lines: codeLines.length,
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// 多行注释
|
|
142
|
+
if (comment.type === "Block") {
|
|
143
|
+
if (isFunctionComment(comment.value, true)) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
const lines = comment.value.split("\n");
|
|
147
|
+
const codeLines = lines.filter(line => {
|
|
148
|
+
const trimmed = line.trim();
|
|
149
|
+
return trimmed !== "*" && trimmed.length > 0 && trimmed; // 过滤掉空行和只包含*的行
|
|
150
|
+
});
|
|
151
|
+
if (codeLines.length >= minLines) {
|
|
152
|
+
context.report({
|
|
153
|
+
node: comment,
|
|
154
|
+
message: `注释掉了 ${codeLines.length} 行代码,请删除或保留为有效代码`,
|
|
155
|
+
data: {
|
|
156
|
+
lines: codeLines.length,
|
|
157
|
+
},
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
},
|
|
166
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "eslint-plugin-better-codes",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "index.js",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"test": "npx eslint ./test.js"
|
|
7
|
+
},
|
|
8
|
+
"keywords": [
|
|
9
|
+
"eslint",
|
|
10
|
+
"eslint-plugin"
|
|
11
|
+
],
|
|
12
|
+
"author": "",
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"description": "eslint代码规范校验自定义插件合集,提升代码质量"
|
|
15
|
+
}
|