mm_eslint 1.4.3 → 1.4.5
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 +336 -0
- package/README_EN.md +336 -0
- package/config.js +626 -573
- package/corrector.js +375 -0
- package/detector.js +1040 -3413
- package/eslint.config.js +25 -0
- package/fix.js +441 -0
- package/handler.js +993 -0
- package/index.js +211 -1164
- package/package.json +59 -49
- package/tip.js +85 -0
- package/util.js +241 -0
- package/validator.js +266 -0
package/index.js
CHANGED
|
@@ -1,90 +1,29 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ESLint命名规范检测插件
|
|
3
|
-
* 版本:
|
|
3
|
+
* 版本: 2.0.0 - 模块化重构版,职责分离
|
|
4
4
|
*/
|
|
5
|
-
|
|
6
|
-
const { Config } = require('./config');
|
|
7
|
-
const { Detector } = require('./detector');
|
|
5
|
+
const { Handler } = require('./handler');
|
|
8
6
|
|
|
9
7
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
8
|
+
* 规则定义类
|
|
9
|
+
* 负责定义ESLint规则配置
|
|
12
10
|
*/
|
|
13
|
-
|
|
14
|
-
var config = new Config({});
|
|
15
|
-
var detector = new Detector(config);
|
|
16
|
-
|
|
11
|
+
class Rules {
|
|
17
12
|
/**
|
|
18
|
-
*
|
|
19
|
-
* @param {object} node AST节点
|
|
20
|
-
* @returns {boolean} 是否为参数名或参数引用
|
|
13
|
+
* 构造函数
|
|
21
14
|
*/
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
return false;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// 检查是否为函数参数声明
|
|
28
|
-
var parent = node.parent;
|
|
29
|
-
if (parent.type === 'FunctionDeclaration' ||
|
|
30
|
-
parent.type === 'FunctionExpression' ||
|
|
31
|
-
parent.type === 'ArrowFunctionExpression') {
|
|
32
|
-
if (parent.params && Array.isArray(parent.params)) {
|
|
33
|
-
for (var i = 0; i < parent.params.length; i++) {
|
|
34
|
-
if (parent.params[i] === node) {
|
|
35
|
-
return true;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// 检查是否为变量声明中的参数
|
|
42
|
-
if (parent.type === 'VariableDeclarator' && parent.id === node) {
|
|
43
|
-
var grand_parent = parent.parent;
|
|
44
|
-
if (grand_parent && grand_parent.type === 'VariableDeclaration') {
|
|
45
|
-
// 检查是否为函数参数
|
|
46
|
-
var great_grand_parent = grand_parent.parent;
|
|
47
|
-
if (great_grand_parent &&
|
|
48
|
-
(great_grand_parent.type === 'FunctionDeclaration' ||
|
|
49
|
-
great_grand_parent.type === 'FunctionExpression' ||
|
|
50
|
-
great_grand_parent.type === 'ArrowFunctionExpression')) {
|
|
51
|
-
return true;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// 检查是否为参数引用(在函数调用中)
|
|
57
|
-
if (node.type === 'Identifier') {
|
|
58
|
-
// 检查是否在函数调用表达式中
|
|
59
|
-
if (parent.type === 'CallExpression' && parent.callee === node) {
|
|
60
|
-
// 检查是否在函数作用域内
|
|
61
|
-
var current_scope = parent;
|
|
62
|
-
while (current_scope) {
|
|
63
|
-
// 检查当前作用域是否为函数
|
|
64
|
-
if (current_scope.type === 'FunctionDeclaration' ||
|
|
65
|
-
current_scope.type === 'FunctionExpression' ||
|
|
66
|
-
current_scope.type === 'ArrowFunctionExpression') {
|
|
67
|
-
// 检查函数参数中是否有同名参数
|
|
68
|
-
if (current_scope.params && Array.isArray(current_scope.params)) {
|
|
69
|
-
for (var i = 0; i < current_scope.params.length; i++) {
|
|
70
|
-
var param = current_scope.params[i];
|
|
71
|
-
if (param.type === 'Identifier' && param.name === node.name) {
|
|
72
|
-
return true;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
break;
|
|
77
|
-
}
|
|
78
|
-
current_scope = current_scope.parent;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
return false;
|
|
15
|
+
constructor() {
|
|
16
|
+
this.handler = new Handler();
|
|
84
17
|
}
|
|
85
18
|
|
|
86
|
-
|
|
87
|
-
|
|
19
|
+
/**
|
|
20
|
+
* 创建类名规则
|
|
21
|
+
* @returns {object} 类名规则配置
|
|
22
|
+
*/
|
|
23
|
+
createClassNameRule() {
|
|
24
|
+
var handler = this.handler;
|
|
25
|
+
|
|
26
|
+
return {
|
|
88
27
|
meta: {
|
|
89
28
|
type: 'suggestion',
|
|
90
29
|
docs: {
|
|
@@ -98,37 +37,49 @@ function createNamingRules() {
|
|
|
98
37
|
create: function (context) {
|
|
99
38
|
return {
|
|
100
39
|
ClassDeclaration: function (node) {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
// 如果有修复建议,添加修复功能
|
|
113
|
-
if (fix_suggestion) {
|
|
114
|
-
report_obj.fix = function(fixer) {
|
|
115
|
-
return fixer.replaceText(node.id, fix_suggestion.fixed_name);
|
|
116
|
-
};
|
|
117
|
-
report_obj.message += ',建议使用: ' + fix_suggestion.fixed_name;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
context.report(report_obj);
|
|
121
|
-
}
|
|
40
|
+
handler.handleClassDeclaration(context, node, node, 'class');
|
|
41
|
+
},
|
|
42
|
+
VariableDeclaration: function (node) {
|
|
43
|
+
handler.handleVariableDeclaration(context, node, node, 'class');
|
|
44
|
+
},
|
|
45
|
+
Property: function (node) {
|
|
46
|
+
handler.handleProperty(context, node, node, 'class');
|
|
47
|
+
},
|
|
48
|
+
AssignmentExpression: function (node) {
|
|
49
|
+
handler.handleAssignmentExpression(context, node, node, 'class');
|
|
122
50
|
},
|
|
51
|
+
ExportDefaultDeclaration: function (node) {
|
|
52
|
+
handler.handleExportDefaultDeclaration(context, node, node, 'class');
|
|
53
|
+
},
|
|
54
|
+
ExportNamedDeclaration: function (node) {
|
|
55
|
+
handler.handleExportNamedDeclaration(context, node, node, 'class');
|
|
56
|
+
},
|
|
57
|
+
ClassExpression: function (node) {
|
|
58
|
+
handler.handleClassExpression(context, node, node, 'class');
|
|
59
|
+
},
|
|
60
|
+
ImportDeclaration: function (node) {
|
|
61
|
+
handler.handleImportDeclaration(context, node, node, 'class');
|
|
62
|
+
},
|
|
63
|
+
Identifier: function (node) {
|
|
64
|
+
handler.handleIdentifier(context, node, node, 'class');
|
|
65
|
+
}
|
|
123
66
|
};
|
|
124
67
|
},
|
|
125
|
-
}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
126
70
|
|
|
127
|
-
|
|
71
|
+
/**
|
|
72
|
+
* 创建类实例名规则
|
|
73
|
+
* @returns {object} 类实例名规则配置
|
|
74
|
+
*/
|
|
75
|
+
createClassInstanceNameRule() {
|
|
76
|
+
var handler = this.handler;
|
|
77
|
+
|
|
78
|
+
return {
|
|
128
79
|
meta: {
|
|
129
80
|
type: 'suggestion',
|
|
130
81
|
docs: {
|
|
131
|
-
description: '
|
|
82
|
+
description: '检测类实例名是否符合命名规范',
|
|
132
83
|
category: 'Stylistic Issues',
|
|
133
84
|
recommended: true,
|
|
134
85
|
},
|
|
@@ -137,71 +88,35 @@ function createNamingRules() {
|
|
|
137
88
|
},
|
|
138
89
|
create: function (context) {
|
|
139
90
|
return {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
var function_name = node.id.name;
|
|
143
|
-
var err = detector._checkFunctionName(function_name, node);
|
|
144
|
-
if (err) {
|
|
145
|
-
// 获取修复建议
|
|
146
|
-
var fix_suggestion = detector._getFixSuggestion(function_name, 'function-name', err.message);
|
|
147
|
-
|
|
148
|
-
var report_obj = {
|
|
149
|
-
node: err.node,
|
|
150
|
-
message: err.message,
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
// 如果有修复建议,添加修复功能
|
|
154
|
-
if (fix_suggestion) {
|
|
155
|
-
report_obj.fix = function(fixer) {
|
|
156
|
-
return fixer.replaceText(node.id, fix_suggestion.fixed_name);
|
|
157
|
-
};
|
|
158
|
-
// 只有当错误消息中不包含建议时才添加建议
|
|
159
|
-
if (!err.message.includes('建议使用:')) {
|
|
160
|
-
report_obj.message += ',建议使用: ' + fix_suggestion.fixed_name;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
context.report(report_obj);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
91
|
+
VariableDeclaration: function (node) {
|
|
92
|
+
handler.handleVariableDeclaration(context, node, node, 'class-instance');
|
|
167
93
|
},
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
// 获取修复建议
|
|
174
|
-
var fix_suggestion = detector._getFixSuggestion(function_name, 'function-name', err.message);
|
|
175
|
-
|
|
176
|
-
var report_obj = {
|
|
177
|
-
node: err.node,
|
|
178
|
-
message: err.message,
|
|
179
|
-
};
|
|
180
|
-
|
|
181
|
-
// 如果有修复建议,添加修复功能
|
|
182
|
-
if (fix_suggestion) {
|
|
183
|
-
report_obj.fix = function(fixer) {
|
|
184
|
-
return fixer.replaceText(node.id, fix_suggestion.fixed_name);
|
|
185
|
-
};
|
|
186
|
-
// 只有当错误消息中不包含建议时才添加建议
|
|
187
|
-
if (!err.message.includes('建议使用:')) {
|
|
188
|
-
report_obj.message += ',建议使用: ' + fix_suggestion.fixed_name;
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
context.report(report_obj);
|
|
193
|
-
}
|
|
194
|
-
}
|
|
94
|
+
Property: function (node) {
|
|
95
|
+
handler.handleProperty(context, node, node, 'class-instance');
|
|
96
|
+
},
|
|
97
|
+
AssignmentExpression: function (node) {
|
|
98
|
+
handler.handleAssignmentExpression(context, node, node, 'class-instance');
|
|
195
99
|
},
|
|
100
|
+
PropertyDefinition: function (node) {
|
|
101
|
+
handler.handlePropertyDefinition(context, node, node, 'class-instance');
|
|
102
|
+
}
|
|
196
103
|
};
|
|
197
104
|
},
|
|
198
|
-
}
|
|
105
|
+
};
|
|
106
|
+
}
|
|
199
107
|
|
|
200
|
-
|
|
108
|
+
/**
|
|
109
|
+
* 创建函数名规则
|
|
110
|
+
* @returns {object} 函数名规则配置
|
|
111
|
+
*/
|
|
112
|
+
createFunctionNameRule() {
|
|
113
|
+
var handler = this.handler;
|
|
114
|
+
|
|
115
|
+
return {
|
|
201
116
|
meta: {
|
|
202
117
|
type: 'suggestion',
|
|
203
118
|
docs: {
|
|
204
|
-
description: '
|
|
119
|
+
description: '检测函数名是否符合命名规范',
|
|
205
120
|
category: 'Stylistic Issues',
|
|
206
121
|
recommended: true,
|
|
207
122
|
},
|
|
@@ -209,191 +124,47 @@ function createNamingRules() {
|
|
|
209
124
|
schema: [],
|
|
210
125
|
},
|
|
211
126
|
create: function (context) {
|
|
212
|
-
var self = this;
|
|
213
|
-
|
|
214
127
|
return {
|
|
128
|
+
FunctionDeclaration: function (node) {
|
|
129
|
+
handler.handleFunctionDeclaration(context, node, node, 'function');
|
|
130
|
+
},
|
|
131
|
+
FunctionExpression: function (node) {
|
|
132
|
+
handler.handleFunctionExpression(context, node, node, 'function');
|
|
133
|
+
},
|
|
134
|
+
ArrowFunctionExpression: function (node) {
|
|
135
|
+
handler.handleArrowFunctionExpression(context, node, node, 'function');
|
|
136
|
+
},
|
|
215
137
|
CallExpression: function (node) {
|
|
216
|
-
|
|
217
|
-
var function_name = node.callee.name;
|
|
218
|
-
|
|
219
|
-
// 检查是否为参数名,如果是参数名则跳过检测(避免与参数名规则冲突)
|
|
220
|
-
if (_isParameterName(node.callee)) {
|
|
221
|
-
return;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
// 只检测函数调用名中的明显错误,如大写开头或蛇形命名
|
|
225
|
-
var err = detector._checkFunctionName(function_name, node);
|
|
226
|
-
if (err && (err.message.includes('不符合camelCase命名风格') || err.message.includes('不符合命名规范'))) {
|
|
227
|
-
// 获取修复建议
|
|
228
|
-
var fix_suggestion = detector._getFixSuggestion(function_name, 'function-name', err.message);
|
|
229
|
-
|
|
230
|
-
// 根据错误类型生成具体的错误消息
|
|
231
|
-
var error_detail = '';
|
|
232
|
-
if (err.message.includes('不符合camelCase命名风格')) {
|
|
233
|
-
error_detail = '不符合camelCase命名风格';
|
|
234
|
-
} else if (err.message.includes('长度过长')) {
|
|
235
|
-
error_detail = '长度过长,最大长度为20字符';
|
|
236
|
-
} else if (err.message.includes('长度过短')) {
|
|
237
|
-
error_detail = '长度过短,最小长度为1字符';
|
|
238
|
-
} else if (err.message.includes('单词过长')) {
|
|
239
|
-
error_detail = '包含的单词过长,最大长度为8字符';
|
|
240
|
-
} else {
|
|
241
|
-
error_detail = '不符合命名规范';
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
var report_obj = {
|
|
245
|
-
node: node.callee,
|
|
246
|
-
message: '函数调用名\'' + function_name + '\'' + error_detail + ',建议使用: ' + (fix_suggestion ? fix_suggestion.fixed_name : '符合规范的名称'),
|
|
247
|
-
};
|
|
248
|
-
|
|
249
|
-
// 如果有修复建议,添加修复功能
|
|
250
|
-
if (fix_suggestion) {
|
|
251
|
-
report_obj.fix = function(fixer) {
|
|
252
|
-
return fixer.replaceText(node.callee, fix_suggestion.fixed_name);
|
|
253
|
-
};
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
context.report(report_obj);
|
|
257
|
-
}
|
|
258
|
-
}
|
|
138
|
+
handler.handleCallExpression(context, node, node, 'function');
|
|
259
139
|
},
|
|
260
|
-
};
|
|
261
|
-
},
|
|
262
|
-
},
|
|
263
|
-
|
|
264
|
-
'method-name': {
|
|
265
|
-
meta: {
|
|
266
|
-
type: 'suggestion',
|
|
267
|
-
docs: {
|
|
268
|
-
description: '检测方法名是否符合命名规范',
|
|
269
|
-
category: 'Stylistic Issues',
|
|
270
|
-
recommended: true,
|
|
271
|
-
},
|
|
272
|
-
fixable: 'code',
|
|
273
|
-
schema: [],
|
|
274
|
-
},
|
|
275
|
-
create: function (context) {
|
|
276
|
-
return {
|
|
277
140
|
MethodDefinition: function (node) {
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
var report_obj = {
|
|
286
|
-
node: err.node,
|
|
287
|
-
message: err.message,
|
|
288
|
-
};
|
|
289
|
-
|
|
290
|
-
// 如果有修复建议,添加修复功能
|
|
291
|
-
if (fix_suggestion) {
|
|
292
|
-
report_obj.fix = function(fixer) {
|
|
293
|
-
return fixer.replaceText(node.key, fix_suggestion.fixed_name);
|
|
294
|
-
};
|
|
295
|
-
// 只有当错误消息中不包含建议时才添加建议
|
|
296
|
-
if (!err.message.includes('建议使用:')) {
|
|
297
|
-
report_obj.message += ',建议使用: ' + fix_suggestion.fixed_name;
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
context.report(report_obj);
|
|
302
|
-
}
|
|
303
|
-
}
|
|
141
|
+
handler.handleMethodDefinition(context, node, node, 'function');
|
|
142
|
+
},
|
|
143
|
+
Property: function (node) {
|
|
144
|
+
handler.handleProperty(context, node, node, 'function');
|
|
145
|
+
},
|
|
146
|
+
PropertyDefinition: function (node) {
|
|
147
|
+
handler.handlePropertyDefinition(context, node, node, 'function');
|
|
304
148
|
},
|
|
305
|
-
|
|
306
|
-
// 处理原型方法定义:ClassName.prototype.method_name = function() {}
|
|
307
149
|
AssignmentExpression: function (node) {
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
node.left.object.property &&
|
|
313
|
-
node.left.object.property.name === 'prototype' &&
|
|
314
|
-
node.left.property &&
|
|
315
|
-
node.left.property.type === 'Identifier' &&
|
|
316
|
-
node.right &&
|
|
317
|
-
(node.right.type === 'FunctionExpression' || node.right.type === 'ArrowFunctionExpression')) {
|
|
318
|
-
|
|
319
|
-
var method_name = node.left.property.name;
|
|
320
|
-
var err = detector._checkMethodName(method_name, node);
|
|
321
|
-
if (err) {
|
|
322
|
-
// 检查是否为建议类型(不是错误)
|
|
323
|
-
if (err.type === 'suggestion') {
|
|
324
|
-
// 建议性提示,直接使用返回的错误信息
|
|
325
|
-
var report_obj = {
|
|
326
|
-
node: node.left.property,
|
|
327
|
-
message: err.message,
|
|
328
|
-
};
|
|
329
|
-
} else {
|
|
330
|
-
// 错误性提示,直接使用检测器返回的错误信息(已经包含推荐建议)
|
|
331
|
-
var report_obj = {
|
|
332
|
-
node: node.left.property,
|
|
333
|
-
message: err.message,
|
|
334
|
-
};
|
|
335
|
-
|
|
336
|
-
// 如果有修复建议,添加修复功能
|
|
337
|
-
var fix_suggestion = detector._getFixSuggestion(method_name, 'method-name', err.message);
|
|
338
|
-
if (fix_suggestion) {
|
|
339
|
-
report_obj.fix = function(fixer) {
|
|
340
|
-
return fixer.replaceText(node.left.property, fix_suggestion.fixed_name);
|
|
341
|
-
};
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
context.report(report_obj);
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
// 处理类实例方法定义:this.method_name = function() {}
|
|
350
|
-
if (node.left &&
|
|
351
|
-
node.left.type === 'MemberExpression' &&
|
|
352
|
-
node.left.object &&
|
|
353
|
-
node.left.object.type === 'ThisExpression' &&
|
|
354
|
-
node.left.property &&
|
|
355
|
-
node.left.property.type === 'Identifier' &&
|
|
356
|
-
node.right &&
|
|
357
|
-
(node.right.type === 'FunctionExpression' || node.right.type === 'ArrowFunctionExpression')) {
|
|
358
|
-
|
|
359
|
-
var method_name = node.left.property.name;
|
|
360
|
-
var err = detector._checkMethodName(method_name, node);
|
|
361
|
-
if (err) {
|
|
362
|
-
// 获取修复建议
|
|
363
|
-
var fix_suggestion = detector._getFixSuggestion(method_name, 'method-name', err.message);
|
|
364
|
-
|
|
365
|
-
// 检查错误信息是否包含推荐词
|
|
366
|
-
var recommendation_match = err.message.match(/建议使用'([^']+)'/);
|
|
367
|
-
var recommended_name = recommendation_match ? recommendation_match[1] : null;
|
|
368
|
-
|
|
369
|
-
var suggestion_text = '符合规范的名称';
|
|
370
|
-
if (fix_suggestion) {
|
|
371
|
-
suggestion_text = fix_suggestion.fixed_name;
|
|
372
|
-
} else if (recommended_name) {
|
|
373
|
-
suggestion_text = recommended_name;
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
var report_obj = {
|
|
377
|
-
node: node.left.property,
|
|
378
|
-
message: '方法名\'' + method_name + '\'不符合命名规范,建议使用: ' + suggestion_text,
|
|
379
|
-
};
|
|
380
|
-
|
|
381
|
-
// 如果有修复建议,添加修复功能
|
|
382
|
-
if (fix_suggestion) {
|
|
383
|
-
report_obj.fix = function(fixer) {
|
|
384
|
-
return fixer.replaceText(node.left.property, fix_suggestion.fixed_name);
|
|
385
|
-
};
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
context.report(report_obj);
|
|
389
|
-
}
|
|
390
|
-
}
|
|
150
|
+
handler.handleAssignmentExpression(context, node, node, 'function');
|
|
151
|
+
},
|
|
152
|
+
VariableDeclaration: function (node) {
|
|
153
|
+
handler.handleVariableDeclaration(context, node, node, 'function');
|
|
391
154
|
},
|
|
392
155
|
};
|
|
393
156
|
},
|
|
394
|
-
}
|
|
157
|
+
};
|
|
158
|
+
}
|
|
395
159
|
|
|
396
|
-
|
|
160
|
+
/**
|
|
161
|
+
* 创建变量名规则
|
|
162
|
+
* @returns {object} 变量名规则配置
|
|
163
|
+
*/
|
|
164
|
+
createVariableNameRule() {
|
|
165
|
+
var handler = this.handler;
|
|
166
|
+
|
|
167
|
+
return {
|
|
397
168
|
meta: {
|
|
398
169
|
type: 'suggestion',
|
|
399
170
|
docs: {
|
|
@@ -407,123 +178,45 @@ function createNamingRules() {
|
|
|
407
178
|
create: function (context) {
|
|
408
179
|
return {
|
|
409
180
|
VariableDeclaration: function (node) {
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
var variable_name = decl.id.name;
|
|
416
|
-
var err = detector._checkVariableName(variable_name, decl);
|
|
417
|
-
if (err) {
|
|
418
|
-
// 获取修复建议
|
|
419
|
-
var fix_suggestion = detector._getFixSuggestion(variable_name, 'variable-name', err.message);
|
|
420
|
-
|
|
421
|
-
var report_obj = {
|
|
422
|
-
node: decl.id,
|
|
423
|
-
message: err.message,
|
|
424
|
-
};
|
|
425
|
-
|
|
426
|
-
// 如果有修复建议,添加修复功能
|
|
427
|
-
if (fix_suggestion) {
|
|
428
|
-
report_obj.fix = function(fixer) {
|
|
429
|
-
return fixer.replaceText(decl.id, fix_suggestion.fixed_name);
|
|
430
|
-
};
|
|
431
|
-
report_obj.message += ',建议使用: ' + fix_suggestion.fixed_name;
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
context.report(report_obj);
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
// 处理解构赋值 - ObjectPattern
|
|
438
|
-
else if (decl.id && decl.id.type === 'ObjectPattern') {
|
|
439
|
-
decl.id.properties.forEach(function(property) {
|
|
440
|
-
if (property.key && property.key.type === 'Identifier') {
|
|
441
|
-
var variable_name = property.key.name;
|
|
442
|
-
var err = detector._checkVariableName(variable_name, decl);
|
|
443
|
-
if (err) {
|
|
444
|
-
// 获取修复建议
|
|
445
|
-
var fix_suggestion = detector._getFixSuggestion(variable_name, 'variable-name', err.message);
|
|
446
|
-
|
|
447
|
-
var report_obj = {
|
|
448
|
-
node: property.key,
|
|
449
|
-
message: err.message,
|
|
450
|
-
};
|
|
451
|
-
|
|
452
|
-
// 如果有修复建议,添加修复功能
|
|
453
|
-
if (fix_suggestion) {
|
|
454
|
-
report_obj.fix = function(fixer) {
|
|
455
|
-
return fixer.replaceText(property.key, fix_suggestion.fixed_name);
|
|
456
|
-
};
|
|
457
|
-
report_obj.message += ',建议使用: ' + fix_suggestion.fixed_name;
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
context.report(report_obj);
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
});
|
|
464
|
-
}
|
|
465
|
-
// 处理解构赋值 - ArrayPattern
|
|
466
|
-
else if (decl.id && decl.id.type === 'ArrayPattern') {
|
|
467
|
-
decl.id.elements.forEach(function(element, index) {
|
|
468
|
-
if (element && element.type === 'Identifier') {
|
|
469
|
-
var variable_name = element.name;
|
|
470
|
-
var err = detector._checkVariableName(variable_name, decl);
|
|
471
|
-
if (err) {
|
|
472
|
-
// 获取修复建议
|
|
473
|
-
var fix_suggestion = detector._getFixSuggestion(variable_name, 'variable-name', err.message);
|
|
474
|
-
|
|
475
|
-
var report_obj = {
|
|
476
|
-
node: element,
|
|
477
|
-
message: err.message,
|
|
478
|
-
};
|
|
479
|
-
|
|
480
|
-
// 如果有修复建议,添加修复功能
|
|
481
|
-
if (fix_suggestion) {
|
|
482
|
-
report_obj.fix = function(fixer) {
|
|
483
|
-
return fixer.replaceText(element, fix_suggestion.fixed_name);
|
|
484
|
-
};
|
|
485
|
-
report_obj.message += ',建议使用: ' + fix_suggestion.fixed_name;
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
context.report(report_obj);
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
});
|
|
492
|
-
}
|
|
493
|
-
});
|
|
181
|
+
handler.handleVariableDeclaration(context, node, node, 'variable');
|
|
182
|
+
},
|
|
183
|
+
ForStatement: function (node) {
|
|
184
|
+
if (node.init && node.init.type === 'VariableDeclaration') {
|
|
185
|
+
handler.handleVariableDeclaration(context, node, node.init, 'variable');
|
|
494
186
|
}
|
|
495
187
|
},
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
'param-name': {
|
|
501
|
-
meta: {
|
|
502
|
-
type: 'suggestion',
|
|
503
|
-
docs: {
|
|
504
|
-
description: '检测参数名是否符合命名规范',
|
|
505
|
-
category: 'Stylistic Issues',
|
|
506
|
-
recommended: true,
|
|
507
|
-
},
|
|
508
|
-
fixable: 'code',
|
|
509
|
-
schema: [],
|
|
510
|
-
},
|
|
511
|
-
create: function (context) {
|
|
512
|
-
return {
|
|
513
|
-
FunctionDeclaration: function (node) {
|
|
514
|
-
_fixParamAndReferences(context, node, detector);
|
|
188
|
+
ForInStatement: function (node) {
|
|
189
|
+
if (node.left && node.left.type === 'VariableDeclaration') {
|
|
190
|
+
handler.handleVariableDeclaration(context, node, node.left, 'variable');
|
|
191
|
+
}
|
|
515
192
|
},
|
|
516
|
-
|
|
517
|
-
|
|
193
|
+
ForOfStatement: function (node) {
|
|
194
|
+
if (node.left && node.left.type === 'VariableDeclaration') {
|
|
195
|
+
handler.handleVariableDeclaration(context, node, node.left, 'variable');
|
|
196
|
+
}
|
|
518
197
|
},
|
|
519
|
-
|
|
520
|
-
|
|
198
|
+
Property: function (node) {
|
|
199
|
+
handler.handleProperty(context, node, node, 'variable');
|
|
521
200
|
},
|
|
201
|
+
PropertyDefinition: function (node) {
|
|
202
|
+
handler.handlePropertyDefinition(context, node, node, 'variable');
|
|
203
|
+
},
|
|
204
|
+
AssignmentExpression: function (node) {
|
|
205
|
+
handler.handleAssignmentExpression(context, node, node, 'variable');
|
|
206
|
+
}
|
|
522
207
|
};
|
|
523
208
|
},
|
|
524
|
-
}
|
|
209
|
+
};
|
|
210
|
+
}
|
|
525
211
|
|
|
526
|
-
|
|
212
|
+
/**
|
|
213
|
+
* 创建常量名规则
|
|
214
|
+
* @returns {object} 常量名规则配置
|
|
215
|
+
*/
|
|
216
|
+
createConstantNameRule() {
|
|
217
|
+
var handler = this.handler;
|
|
218
|
+
|
|
219
|
+
return {
|
|
527
220
|
meta: {
|
|
528
221
|
type: 'suggestion',
|
|
529
222
|
docs: {
|
|
@@ -537,761 +230,115 @@ function createNamingRules() {
|
|
|
537
230
|
create: function (context) {
|
|
538
231
|
return {
|
|
539
232
|
VariableDeclaration: function (node) {
|
|
540
|
-
|
|
541
|
-
node.declarations.forEach(function(decl) {
|
|
542
|
-
// 处理简单变量声明
|
|
543
|
-
if (decl.id && decl.id.type === 'Identifier') {
|
|
544
|
-
var constant_name = decl.id.name;
|
|
545
|
-
var err = detector._checkConstantName(constant_name, decl, decl.init);
|
|
546
|
-
if (err) {
|
|
547
|
-
var report_obj = {
|
|
548
|
-
node: decl.id,
|
|
549
|
-
message: err.message,
|
|
550
|
-
};
|
|
551
|
-
|
|
552
|
-
// 如果错误是"应该使用let而不是const",提供const→let修复功能
|
|
553
|
-
if (err.message.includes('应该使用let而不是const')) {
|
|
554
|
-
report_obj.fix = function(fixer) {
|
|
555
|
-
// 替换const为let
|
|
556
|
-
var const_range = [node.range[0], node.range[0] + 5]; // const的位置
|
|
557
|
-
return fixer.replaceTextRange(const_range, 'let');
|
|
558
|
-
};
|
|
559
|
-
report_obj.message += ',建议将const改为let';
|
|
560
|
-
}
|
|
561
|
-
// 否则提供命名风格修复建议
|
|
562
|
-
else {
|
|
563
|
-
// 使用检测器返回的规则类型(优先)
|
|
564
|
-
var rule_type = err.rule_type || 'constant-name';
|
|
565
|
-
|
|
566
|
-
// 如果没有返回规则类型,根据错误信息确定正确的规则类型
|
|
567
|
-
if (!err.rule_type) {
|
|
568
|
-
if (err.message.includes('函数名')) {
|
|
569
|
-
rule_type = 'function-name';
|
|
570
|
-
} else if (err.message.includes('变量名')) {
|
|
571
|
-
rule_type = 'variable-name';
|
|
572
|
-
} else if (err.message.includes('类名')) {
|
|
573
|
-
rule_type = 'class-name';
|
|
574
|
-
} else if (err.message.includes('属性名')) {
|
|
575
|
-
rule_type = 'property-name';
|
|
576
|
-
} else if (err.message.includes('方法名')) {
|
|
577
|
-
rule_type = 'method-name';
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
// 获取修复建议
|
|
582
|
-
var fix_suggestion = detector._getFixSuggestion(constant_name, rule_type, err.message);
|
|
583
|
-
|
|
584
|
-
// 如果有修复建议,添加修复功能
|
|
585
|
-
if (fix_suggestion) {
|
|
586
|
-
report_obj.fix = function(fixer) {
|
|
587
|
-
return fixer.replaceText(decl.id, fix_suggestion.fixed_name);
|
|
588
|
-
};
|
|
589
|
-
|
|
590
|
-
// 只有当错误消息中不包含建议时才添加建议
|
|
591
|
-
if (!err.message.includes('建议使用:')) {
|
|
592
|
-
report_obj.message += ',建议使用: ' + fix_suggestion.fixed_name;
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
// 设置正确的规则类型用于ESLint报告
|
|
597
|
-
report_obj.ruleId = 'mm_eslint/' + rule_type;
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
context.report(report_obj);
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
|
-
// 处理解构赋值 - ObjectPattern
|
|
604
|
-
else if (decl.id && decl.id.type === 'ObjectPattern') {
|
|
605
|
-
decl.id.properties.forEach(function(property) {
|
|
606
|
-
if (property.key && property.key.type === 'Identifier') {
|
|
607
|
-
var constant_name = property.key.name;
|
|
608
|
-
// 对于解构赋值,使用专门的检测方法
|
|
609
|
-
var err = detector._checkConstantNameForDestructuring(constant_name, property.key);
|
|
610
|
-
if (err) {
|
|
611
|
-
var report_obj = {
|
|
612
|
-
node: property.key,
|
|
613
|
-
message: err.message,
|
|
614
|
-
};
|
|
615
|
-
|
|
616
|
-
// 如果错误是"应该使用let而不是const",提供const→let修复功能
|
|
617
|
-
if (err.message.includes('应该使用let而不是const')) {
|
|
618
|
-
report_obj.fix = function(fixer) {
|
|
619
|
-
// 替换const为let
|
|
620
|
-
var const_range = [node.range[0], node.range[0] + 5]; // const的位置
|
|
621
|
-
return fixer.replaceTextRange(const_range, 'let');
|
|
622
|
-
};
|
|
623
|
-
report_obj.message += ',建议将const改为let';
|
|
624
|
-
}
|
|
625
|
-
// 否则提供命名风格修复建议
|
|
626
|
-
else {
|
|
627
|
-
// 根据错误信息确定正确的规则类型
|
|
628
|
-
var rule_type = 'constant-name';
|
|
629
|
-
if (err.message.includes('函数名')) {
|
|
630
|
-
rule_type = 'function-name';
|
|
631
|
-
} else if (err.message.includes('变量名')) {
|
|
632
|
-
rule_type = 'variable-name';
|
|
633
|
-
} else if (err.message.includes('类名')) {
|
|
634
|
-
rule_type = 'class-name';
|
|
635
|
-
} else if (err.message.includes('属性名')) {
|
|
636
|
-
rule_type = 'property-name';
|
|
637
|
-
} else if (err.message.includes('方法名')) {
|
|
638
|
-
rule_type = 'method-name';
|
|
639
|
-
}
|
|
640
|
-
|
|
641
|
-
// 获取修复建议
|
|
642
|
-
var fix_suggestion = detector._getFixSuggestion(constant_name, rule_type, err.message);
|
|
643
|
-
|
|
644
|
-
// 如果有修复建议,添加修复功能
|
|
645
|
-
if (fix_suggestion) {
|
|
646
|
-
report_obj.fix = function(fixer) {
|
|
647
|
-
return fixer.replaceText(property.key, fix_suggestion.fixed_name);
|
|
648
|
-
};
|
|
649
|
-
report_obj.message += ',建议使用: ' + fix_suggestion.fixed_name;
|
|
650
|
-
}
|
|
651
|
-
}
|
|
652
|
-
|
|
653
|
-
context.report(report_obj);
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
});
|
|
657
|
-
}
|
|
658
|
-
// 处理解构赋值 - ArrayPattern
|
|
659
|
-
else if (decl.id && decl.id.type === 'ArrayPattern') {
|
|
660
|
-
decl.id.elements.forEach(function(element, index) {
|
|
661
|
-
if (element && element.type === 'Identifier') {
|
|
662
|
-
var constant_name = element.name;
|
|
663
|
-
// 对于解构赋值,使用专门的检测方法
|
|
664
|
-
var err = detector._checkConstantNameForDestructuring(constant_name, element);
|
|
665
|
-
if (err) {
|
|
666
|
-
// 根据错误信息确定正确的规则类型
|
|
667
|
-
var rule_type = 'variable-name';
|
|
668
|
-
if (err.message.includes('函数名')) {
|
|
669
|
-
rule_type = 'function-name';
|
|
670
|
-
} else if (err.message.includes('变量名')) {
|
|
671
|
-
rule_type = 'variable-name';
|
|
672
|
-
} else if (err.message.includes('类名')) {
|
|
673
|
-
rule_type = 'class-name';
|
|
674
|
-
} else if (err.message.includes('属性名')) {
|
|
675
|
-
rule_type = 'property-name';
|
|
676
|
-
} else if (err.message.includes('方法名')) {
|
|
677
|
-
rule_type = 'method-name';
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
// 获取修复建议
|
|
681
|
-
var fix_suggestion = detector._getFixSuggestion(constant_name, rule_type, err.message);
|
|
682
|
-
|
|
683
|
-
var report_obj = {
|
|
684
|
-
node: element,
|
|
685
|
-
message: err.message,
|
|
686
|
-
};
|
|
687
|
-
|
|
688
|
-
// 如果有修复建议,添加修复功能
|
|
689
|
-
if (fix_suggestion) {
|
|
690
|
-
report_obj.fix = function(fixer) {
|
|
691
|
-
return fixer.replaceText(element, fix_suggestion.fixed_name);
|
|
692
|
-
};
|
|
693
|
-
report_obj.message += ',建议使用: ' + fix_suggestion.fixed_name;
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
context.report(report_obj);
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
});
|
|
700
|
-
}
|
|
701
|
-
});
|
|
702
|
-
}
|
|
233
|
+
handler.handleVariableDeclaration(context, node, node, 'constant');
|
|
703
234
|
},
|
|
704
|
-
};
|
|
705
|
-
},
|
|
706
|
-
},
|
|
707
|
-
|
|
708
|
-
'property-value-name': {
|
|
709
|
-
meta: {
|
|
710
|
-
type: 'suggestion',
|
|
711
|
-
docs: {
|
|
712
|
-
description: '属性值名命名规范检测',
|
|
713
|
-
category: 'Stylistic Issues',
|
|
714
|
-
recommended: true
|
|
715
|
-
},
|
|
716
|
-
fixable: 'code',
|
|
717
|
-
schema: []
|
|
718
|
-
},
|
|
719
|
-
create: function (context) {
|
|
720
|
-
return {
|
|
721
235
|
Property: function (node) {
|
|
722
|
-
|
|
723
|
-
var prop_name = node.key.name;
|
|
724
|
-
|
|
725
|
-
// 直接跳过null值和未赋值属性的检测
|
|
726
|
-
// 注意:null值的类型是Literal,但value为null
|
|
727
|
-
var is_null_value = node.value && node.value.type === 'Literal' && node.value.value === null;
|
|
728
|
-
var is_undefined_value = !node.value;
|
|
729
|
-
|
|
730
|
-
if (is_null_value || is_undefined_value) {
|
|
731
|
-
// 对于null值和未赋值属性,直接跳过检测,不报错
|
|
732
|
-
return;
|
|
733
|
-
}
|
|
734
|
-
|
|
735
|
-
// 传递祖父节点信息,用于第三方库排除检测
|
|
736
|
-
var parent_info = {
|
|
737
|
-
node: node.parent,
|
|
738
|
-
parent: node.parent ? node.parent.parent : null
|
|
739
|
-
};
|
|
740
|
-
|
|
741
|
-
var err = detector._checkPropertyName(
|
|
742
|
-
prop_name,
|
|
743
|
-
node,
|
|
744
|
-
node.value,
|
|
745
|
-
parent_info,
|
|
746
|
-
);
|
|
747
|
-
|
|
748
|
-
// 只处理属性值名相关的错误
|
|
749
|
-
if (err && err.rule_type === 'property-value-name') {
|
|
750
|
-
// 获取修复建议
|
|
751
|
-
var fix_suggestion = detector._getFixSuggestion(prop_name, 'property-value-name', err.message);
|
|
752
|
-
|
|
753
|
-
var report_obj = {
|
|
754
|
-
node: err.node,
|
|
755
|
-
message: err.message,
|
|
756
|
-
};
|
|
757
|
-
|
|
758
|
-
// 如果有修复建议,添加修复功能
|
|
759
|
-
if (fix_suggestion) {
|
|
760
|
-
report_obj.fix = function(fixer) {
|
|
761
|
-
return fixer.replaceText(node.key, fix_suggestion.fixed_name);
|
|
762
|
-
};
|
|
763
|
-
report_obj.message += ',建议使用: ' + fix_suggestion.fixed_name;
|
|
764
|
-
}
|
|
765
|
-
|
|
766
|
-
context.report(report_obj);
|
|
767
|
-
}
|
|
768
|
-
}
|
|
769
|
-
},
|
|
770
|
-
// 检测类实例属性 (this.xxx)
|
|
771
|
-
AssignmentExpression: function (node) {
|
|
772
|
-
// 检查是否是 this.xxx = value 形式的赋值
|
|
773
|
-
if (node.left && node.left.type === 'MemberExpression' &&
|
|
774
|
-
node.left.object && node.left.object.type === 'ThisExpression' &&
|
|
775
|
-
node.left.property && node.left.property.type === 'Identifier') {
|
|
776
|
-
|
|
777
|
-
// 排除类实例方法:this.method_name = function() {}
|
|
778
|
-
var is_instance_method =
|
|
779
|
-
node.right &&
|
|
780
|
-
(node.right.type === 'FunctionExpression' || node.right.type === 'ArrowFunctionExpression');
|
|
781
|
-
|
|
782
|
-
if (is_instance_method) {
|
|
783
|
-
// 类实例方法由 method-name 规则处理,跳过
|
|
784
|
-
return;
|
|
785
|
-
}
|
|
786
|
-
|
|
787
|
-
var prop_name = node.left.property.name;
|
|
788
|
-
|
|
789
|
-
var parent_info = {
|
|
790
|
-
node: node.parent,
|
|
791
|
-
parent: node.parent ? node.parent.parent : null
|
|
792
|
-
};
|
|
793
|
-
|
|
794
|
-
var err = detector._checkPropertyName(
|
|
795
|
-
prop_name,
|
|
796
|
-
node.left.property,
|
|
797
|
-
node.right,
|
|
798
|
-
parent_info,
|
|
799
|
-
);
|
|
800
|
-
|
|
801
|
-
// 处理所有属性相关的错误类型,但排除 property-instance-class-name(由专门规则处理)
|
|
802
|
-
if (err && err.rule_type && err.rule_type.startsWith('property-') &&
|
|
803
|
-
err.rule_type !== 'property-instance-class-name') {
|
|
804
|
-
// 获取修复建议
|
|
805
|
-
var fix_suggestion = detector._getFixSuggestion(prop_name, err.rule_type, err.message);
|
|
806
|
-
|
|
807
|
-
var report_obj = {
|
|
808
|
-
node: node.left.property,
|
|
809
|
-
message: err.message,
|
|
810
|
-
};
|
|
811
|
-
|
|
812
|
-
// 如果有修复建议,添加修复功能
|
|
813
|
-
if (fix_suggestion) {
|
|
814
|
-
report_obj.fix = function(fixer) {
|
|
815
|
-
return fixer.replaceText(node.left.property, fix_suggestion.fixed_name);
|
|
816
|
-
};
|
|
817
|
-
report_obj.message += ',建议使用: ' + fix_suggestion.fixed_name;
|
|
818
|
-
}
|
|
819
|
-
|
|
820
|
-
context.report(report_obj);
|
|
821
|
-
}
|
|
822
|
-
}
|
|
236
|
+
handler.handleProperty(context, node, node, 'constant');
|
|
823
237
|
},
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
if (
|
|
827
|
-
node.left &&
|
|
828
|
-
node.left.type === 'MemberExpression' &&
|
|
829
|
-
node.left.property &&
|
|
830
|
-
node.left.property.name
|
|
831
|
-
) {
|
|
832
|
-
// 排除原型方法:ClassName.prototype.method_name = function() {}
|
|
833
|
-
var is_prototype_method =
|
|
834
|
-
node.left.object &&
|
|
835
|
-
node.left.object.type === 'MemberExpression' &&
|
|
836
|
-
node.left.object.property &&
|
|
837
|
-
node.left.object.property.name === 'prototype' &&
|
|
838
|
-
node.right &&
|
|
839
|
-
(node.right.type === 'FunctionExpression' || node.right.type === 'ArrowFunctionExpression');
|
|
840
|
-
|
|
841
|
-
if (is_prototype_method) {
|
|
842
|
-
// 原型方法由 method-name 规则处理,跳过
|
|
843
|
-
return;
|
|
844
|
-
}
|
|
845
|
-
|
|
846
|
-
var prop_name = node.left.property.name;
|
|
847
|
-
|
|
848
|
-
// 直接跳过null值和未赋值属性的检测
|
|
849
|
-
// 注意:null值的类型是Literal,但value为null
|
|
850
|
-
var is_null_value = node.right && node.right.type === 'Literal' && node.right.value === null;
|
|
851
|
-
var is_undefined_value = !node.right;
|
|
852
|
-
|
|
853
|
-
if (is_null_value || is_undefined_value) {
|
|
854
|
-
// 对于null值和未赋值属性,直接跳过检测,不报错
|
|
855
|
-
return;
|
|
856
|
-
}
|
|
857
|
-
|
|
858
|
-
var err = detector._checkPropertyName(
|
|
859
|
-
prop_name,
|
|
860
|
-
node,
|
|
861
|
-
node.right,
|
|
862
|
-
node.parent,
|
|
863
|
-
);
|
|
864
|
-
|
|
865
|
-
// 只处理属性值名相关的错误
|
|
866
|
-
if (err && err.rule_type === 'property-value-name') {
|
|
867
|
-
// 获取修复建议
|
|
868
|
-
var fix_suggestion = detector._getFixSuggestion(prop_name, 'property-value-name', err.message);
|
|
869
|
-
|
|
870
|
-
var report_obj = {
|
|
871
|
-
node: err.node,
|
|
872
|
-
message: err.message,
|
|
873
|
-
};
|
|
874
|
-
|
|
875
|
-
// 如果有修复建议,添加修复功能
|
|
876
|
-
if (fix_suggestion) {
|
|
877
|
-
report_obj.fix = function(fixer) {
|
|
878
|
-
return fixer.replaceText(node.left.property, fix_suggestion.fixed_name);
|
|
879
|
-
};
|
|
880
|
-
report_obj.message += ',建议使用: ' + fix_suggestion.fixed_name;
|
|
881
|
-
}
|
|
882
|
-
|
|
883
|
-
context.report(report_obj);
|
|
884
|
-
}
|
|
885
|
-
}
|
|
886
|
-
},
|
|
887
|
-
};
|
|
888
|
-
},
|
|
889
|
-
},
|
|
890
|
-
|
|
891
|
-
'property-method-name': {
|
|
892
|
-
meta: {
|
|
893
|
-
type: 'suggestion',
|
|
894
|
-
docs: {
|
|
895
|
-
description: '属性方法名命名规范检测',
|
|
896
|
-
category: 'Stylistic Issues',
|
|
897
|
-
recommended: true
|
|
898
|
-
},
|
|
899
|
-
fixable: 'code',
|
|
900
|
-
schema: []
|
|
901
|
-
},
|
|
902
|
-
create: function (context) {
|
|
903
|
-
return {
|
|
904
|
-
Property: function (node) {
|
|
905
|
-
if (node.key && node.key.name) {
|
|
906
|
-
var prop_name = node.key.name;
|
|
907
|
-
|
|
908
|
-
// 传递祖父节点信息,用于第三方库排除检测
|
|
909
|
-
var parent_info = {
|
|
910
|
-
node: node.parent,
|
|
911
|
-
parent: node.parent ? node.parent.parent : null
|
|
912
|
-
};
|
|
913
|
-
|
|
914
|
-
var err = detector._checkPropertyName(
|
|
915
|
-
prop_name,
|
|
916
|
-
node,
|
|
917
|
-
node.value,
|
|
918
|
-
parent_info,
|
|
919
|
-
);
|
|
920
|
-
|
|
921
|
-
// 只处理属性方法名相关的错误
|
|
922
|
-
if (err && err.rule_type === 'property-method-name') {
|
|
923
|
-
// 获取修复建议
|
|
924
|
-
var fix_suggestion = detector._getFixSuggestion(prop_name, 'property-method-name', err.message);
|
|
925
|
-
|
|
926
|
-
var report_obj = {
|
|
927
|
-
node: err.node,
|
|
928
|
-
message: err.message,
|
|
929
|
-
};
|
|
930
|
-
|
|
931
|
-
// 如果有修复建议,添加修复功能
|
|
932
|
-
if (fix_suggestion) {
|
|
933
|
-
report_obj.fix = function(fixer) {
|
|
934
|
-
return fixer.replaceText(node.key, fix_suggestion.fixed_name);
|
|
935
|
-
};
|
|
936
|
-
report_obj.message += ',建议使用: ' + fix_suggestion.fixed_name;
|
|
937
|
-
}
|
|
938
|
-
|
|
939
|
-
context.report(report_obj);
|
|
940
|
-
}
|
|
941
|
-
}
|
|
238
|
+
PropertyDefinition: function (node) {
|
|
239
|
+
handler.handlePropertyDefinition(context, node, node, 'constant');
|
|
942
240
|
},
|
|
241
|
+
AssignmentExpression: function (node) {
|
|
242
|
+
handler.handleAssignmentExpression(context, node, node, 'constant');
|
|
243
|
+
}
|
|
943
244
|
};
|
|
944
245
|
},
|
|
945
|
-
}
|
|
246
|
+
};
|
|
247
|
+
}
|
|
946
248
|
|
|
947
|
-
|
|
249
|
+
/**
|
|
250
|
+
* 创建参数名规则
|
|
251
|
+
* @returns {object} 参数名规则配置
|
|
252
|
+
*/
|
|
253
|
+
createParamNameRule() {
|
|
254
|
+
var handler = this.handler;
|
|
255
|
+
|
|
256
|
+
return {
|
|
948
257
|
meta: {
|
|
949
258
|
type: 'suggestion',
|
|
950
259
|
docs: {
|
|
951
|
-
description: '
|
|
260
|
+
description: '检测参数名是否符合命名规范',
|
|
952
261
|
category: 'Stylistic Issues',
|
|
953
|
-
recommended: true
|
|
262
|
+
recommended: true,
|
|
954
263
|
},
|
|
955
264
|
fixable: 'code',
|
|
956
|
-
schema: []
|
|
265
|
+
schema: [],
|
|
957
266
|
},
|
|
958
267
|
create: function (context) {
|
|
959
268
|
return {
|
|
960
|
-
|
|
961
|
-
if (node.
|
|
962
|
-
var
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
prop_name,
|
|
972
|
-
node,
|
|
973
|
-
node.value,
|
|
974
|
-
parent_info,
|
|
975
|
-
);
|
|
976
|
-
|
|
977
|
-
// 只处理属性类名相关的错误
|
|
978
|
-
if (err && err.rule_type === 'property-class-name') {
|
|
979
|
-
// 获取修复建议
|
|
980
|
-
var fix_suggestion = detector._getFixSuggestion(prop_name, 'property-class-name', err.message);
|
|
981
|
-
|
|
982
|
-
var report_obj = {
|
|
983
|
-
node: err.node,
|
|
984
|
-
message: err.message,
|
|
985
|
-
};
|
|
986
|
-
|
|
987
|
-
// 如果有修复建议,添加修复功能
|
|
988
|
-
if (fix_suggestion) {
|
|
989
|
-
report_obj.fix = function(fixer) {
|
|
990
|
-
return fixer.replaceText(node.key, fix_suggestion.fixed_name);
|
|
991
|
-
};
|
|
992
|
-
report_obj.message += ',建议使用: ' + fix_suggestion.fixed_name;
|
|
269
|
+
FunctionDeclaration: function (node) {
|
|
270
|
+
if (node.params && node.params.length > 0) {
|
|
271
|
+
for (var i = 0; i < node.params.length; i++) {
|
|
272
|
+
var param = node.params[i];
|
|
273
|
+
if (param.type === 'Identifier') {
|
|
274
|
+
var result = handler.detector.detect(param, param.name);
|
|
275
|
+
if (result) {
|
|
276
|
+
result.node = param;
|
|
277
|
+
result.fix = handler.fix.createParamFixFunction(context, param, result);
|
|
278
|
+
context.report(result);
|
|
279
|
+
}
|
|
993
280
|
}
|
|
994
|
-
|
|
995
|
-
context.report(report_obj);
|
|
996
281
|
}
|
|
997
282
|
}
|
|
998
283
|
},
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
},
|
|
1011
|
-
fixable: 'code',
|
|
1012
|
-
schema: []
|
|
1013
|
-
},
|
|
1014
|
-
create: function (context) {
|
|
1015
|
-
return {
|
|
1016
|
-
// 检测对象字面量中的属性实例类名
|
|
1017
|
-
Property: function (node) {
|
|
1018
|
-
if (node.key && node.key.name) {
|
|
1019
|
-
var prop_name = node.key.name;
|
|
1020
|
-
|
|
1021
|
-
// 传递祖父节点信息,用于第三方库排除检测
|
|
1022
|
-
var parent_info = {
|
|
1023
|
-
node: node.parent,
|
|
1024
|
-
parent: node.parent ? node.parent.parent : null
|
|
1025
|
-
};
|
|
1026
|
-
|
|
1027
|
-
// 检测属性命名
|
|
1028
|
-
var err = detector._checkPropertyName(
|
|
1029
|
-
prop_name,
|
|
1030
|
-
node.key,
|
|
1031
|
-
node.value,
|
|
1032
|
-
parent_info,
|
|
1033
|
-
);
|
|
1034
|
-
|
|
1035
|
-
// 只处理属性实例类名相关的错误
|
|
1036
|
-
if (err && err.rule_type === 'property-instance-class-name') {
|
|
1037
|
-
// 获取修复建议
|
|
1038
|
-
var fix_suggestion = detector._getFixSuggestion(prop_name, 'property-instance-class-name', err.message);
|
|
1039
|
-
|
|
1040
|
-
var report_obj = {
|
|
1041
|
-
node: err.node,
|
|
1042
|
-
message: err.message,
|
|
1043
|
-
};
|
|
1044
|
-
|
|
1045
|
-
// 如果有修复建议,添加修复功能
|
|
1046
|
-
if (fix_suggestion) {
|
|
1047
|
-
report_obj.fix = function(fixer) {
|
|
1048
|
-
return fixer.replaceText(node.key, fix_suggestion.fixed_name);
|
|
1049
|
-
};
|
|
1050
|
-
report_obj.message += ',建议使用: ' + fix_suggestion.fixed_name;
|
|
284
|
+
FunctionExpression: function (node) {
|
|
285
|
+
if (node.params && node.params.length > 0) {
|
|
286
|
+
for (var i = 0; i < node.params.length; i++) {
|
|
287
|
+
var param = node.params[i];
|
|
288
|
+
if (param.type === 'Identifier') {
|
|
289
|
+
var result = handler.detector.detect(param, param.name);
|
|
290
|
+
if (result) {
|
|
291
|
+
result.node = param;
|
|
292
|
+
result.fix = handler.fix.createParamFixFunction(context, param, result);
|
|
293
|
+
context.report(result);
|
|
294
|
+
}
|
|
1051
295
|
}
|
|
1052
|
-
|
|
1053
|
-
context.report(report_obj);
|
|
1054
296
|
}
|
|
1055
297
|
}
|
|
1056
298
|
},
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
(node.right.type === 'FunctionExpression' || node.right.type === 'ArrowFunctionExpression');
|
|
1069
|
-
|
|
1070
|
-
if (is_instance_method) {
|
|
1071
|
-
// 类实例方法由 method-name 规则处理,跳过
|
|
1072
|
-
return;
|
|
1073
|
-
}
|
|
1074
|
-
|
|
1075
|
-
var prop_name = node.left.property.name;
|
|
1076
|
-
|
|
1077
|
-
var parent_info = {
|
|
1078
|
-
node: node.parent,
|
|
1079
|
-
parent: node.parent ? node.parent.parent : null
|
|
1080
|
-
};
|
|
1081
|
-
|
|
1082
|
-
// 检测属性命名
|
|
1083
|
-
var err = detector._checkPropertyName(
|
|
1084
|
-
prop_name,
|
|
1085
|
-
node.left.property,
|
|
1086
|
-
node.right,
|
|
1087
|
-
parent_info,
|
|
1088
|
-
);
|
|
1089
|
-
|
|
1090
|
-
// 只处理属性实例类名相关的错误
|
|
1091
|
-
if (err && err.rule_type === 'property-instance-class-name') {
|
|
1092
|
-
// 获取修复建议
|
|
1093
|
-
var fix_suggestion = detector._getFixSuggestion(prop_name, 'property-instance-class-name', err.message);
|
|
1094
|
-
|
|
1095
|
-
var report_obj = {
|
|
1096
|
-
node: err.node,
|
|
1097
|
-
message: err.message,
|
|
1098
|
-
};
|
|
1099
|
-
|
|
1100
|
-
// 如果有修复建议,添加修复功能
|
|
1101
|
-
if (fix_suggestion) {
|
|
1102
|
-
report_obj.fix = function(fixer) {
|
|
1103
|
-
return fixer.replaceText(node.left.property, fix_suggestion.fixed_name);
|
|
1104
|
-
};
|
|
1105
|
-
report_obj.message += ',建议使用: ' + fix_suggestion.fixed_name;
|
|
299
|
+
ArrowFunctionExpression: function (node) {
|
|
300
|
+
if (node.params && node.params.length > 0) {
|
|
301
|
+
for (var i = 0; i < node.params.length; i++) {
|
|
302
|
+
var param = node.params[i];
|
|
303
|
+
if (param.type === 'Identifier') {
|
|
304
|
+
var result = handler.detector.detect(param, param.name);
|
|
305
|
+
if (result) {
|
|
306
|
+
result.node = param;
|
|
307
|
+
result.fix = handler.fix.createParamFixFunction(context, param, result);
|
|
308
|
+
context.report(result);
|
|
309
|
+
}
|
|
1106
310
|
}
|
|
1107
|
-
|
|
1108
|
-
context.report(report_obj);
|
|
1109
311
|
}
|
|
1110
312
|
}
|
|
1111
|
-
}
|
|
1112
|
-
};
|
|
1113
|
-
},
|
|
1114
|
-
},
|
|
1115
|
-
|
|
1116
|
-
'param-reference-consistency': {
|
|
1117
|
-
meta: {
|
|
1118
|
-
type: 'problem',
|
|
1119
|
-
docs: {
|
|
1120
|
-
description: '检测参数声明与函数内部引用是否一致',
|
|
1121
|
-
category: 'Possible Errors',
|
|
1122
|
-
recommended: true,
|
|
1123
|
-
},
|
|
1124
|
-
fixable: 'code',
|
|
1125
|
-
schema: [],
|
|
1126
|
-
},
|
|
1127
|
-
create: function (context) {
|
|
1128
|
-
return {
|
|
1129
|
-
FunctionDeclaration: function (node) {
|
|
1130
|
-
detector._checkParamReferences(context, node);
|
|
1131
|
-
},
|
|
1132
|
-
FunctionExpression: function (node) {
|
|
1133
|
-
detector._checkParamReferences(context, node);
|
|
1134
|
-
},
|
|
1135
|
-
ArrowFunctionExpression: function (node) {
|
|
1136
|
-
detector._checkParamReferences(context, node);
|
|
1137
|
-
},
|
|
313
|
+
}
|
|
1138
314
|
};
|
|
1139
315
|
},
|
|
1140
|
-
}
|
|
1141
|
-
}
|
|
1142
|
-
}
|
|
316
|
+
};
|
|
317
|
+
}
|
|
1143
318
|
|
|
1144
|
-
/**
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
var param_name = param.name;
|
|
1159
|
-
var err = detector._checkParamName(param_name, param);
|
|
1160
|
-
if (err) {
|
|
1161
|
-
var fix_suggestion = detector._getFixSuggestion(param_name, 'param-name', err.message);
|
|
1162
|
-
if (fix_suggestion && fix_suggestion.fixed_name !== param_name) {
|
|
1163
|
-
param_fixes.push({
|
|
1164
|
-
param_node: param,
|
|
1165
|
-
old_name: param_name,
|
|
1166
|
-
new_name: fix_suggestion.fixed_name,
|
|
1167
|
-
message: err.message + ',建议使用: ' + fix_suggestion.fixed_name
|
|
1168
|
-
});
|
|
1169
|
-
}
|
|
1170
|
-
}
|
|
1171
|
-
}
|
|
1172
|
-
});
|
|
1173
|
-
|
|
1174
|
-
// 如果没有需要修复的参数,直接返回
|
|
1175
|
-
if (param_fixes.length === 0) return;
|
|
1176
|
-
|
|
1177
|
-
// 分步修复:先修复参数声明,然后单独检测引用不一致问题
|
|
1178
|
-
param_fixes.forEach(function(fix_info) {
|
|
1179
|
-
// 第一步:修复参数声明
|
|
1180
|
-
context.report({
|
|
1181
|
-
node: fix_info.param_node,
|
|
1182
|
-
message: fix_info.message,
|
|
1183
|
-
fix: function(fixer) {
|
|
1184
|
-
return fixer.replaceText(fix_info.param_node, fix_info.new_name);
|
|
1185
|
-
}
|
|
1186
|
-
});
|
|
1187
|
-
|
|
1188
|
-
// 第二步:检测并修复函数体内的引用不一致问题
|
|
1189
|
-
_checkParamReferenceInconsistencies(context, node, fix_info);
|
|
1190
|
-
});
|
|
319
|
+
/**
|
|
320
|
+
* 获取所有规则
|
|
321
|
+
* @returns {object} 所有规则配置
|
|
322
|
+
*/
|
|
323
|
+
getAllRules() {
|
|
324
|
+
return {
|
|
325
|
+
'class-name': this.createClassNameRule(),
|
|
326
|
+
'class-instance-name': this.createClassInstanceNameRule(),
|
|
327
|
+
'function-name': this.createFunctionNameRule(),
|
|
328
|
+
'variable-name': this.createVariableNameRule(),
|
|
329
|
+
'constant-name': this.createConstantNameRule(),
|
|
330
|
+
'param-name': this.createParamNameRule()
|
|
331
|
+
};
|
|
332
|
+
}
|
|
1191
333
|
}
|
|
1192
334
|
|
|
1193
335
|
/**
|
|
1194
|
-
*
|
|
1195
|
-
* @
|
|
1196
|
-
* @param {object} node 函数节点
|
|
1197
|
-
* @param {object} fix_info 修复信息
|
|
336
|
+
* 创建ESLint规则配置
|
|
337
|
+
* @returns {object} ESLint规则配置对象
|
|
1198
338
|
*/
|
|
1199
|
-
function
|
|
1200
|
-
var
|
|
1201
|
-
|
|
1202
|
-
// 使用深度优先搜索遍历AST
|
|
1203
|
-
function findIdentifierReferences(astNode, oldName) {
|
|
1204
|
-
var references = [];
|
|
1205
|
-
var visited = new Set();
|
|
1206
|
-
|
|
1207
|
-
function traverse(currentNode) {
|
|
1208
|
-
// 防止循环引用导致的无限递归
|
|
1209
|
-
if (!currentNode || visited.has(currentNode) || typeof currentNode !== 'object') {
|
|
1210
|
-
return;
|
|
1211
|
-
}
|
|
1212
|
-
visited.add(currentNode);
|
|
1213
|
-
|
|
1214
|
-
// 检查当前节点是否为标识符节点
|
|
1215
|
-
if (currentNode.type === 'Identifier' && currentNode.name === oldName) {
|
|
1216
|
-
// 排除参数声明节点本身
|
|
1217
|
-
if (currentNode !== fix_info.param_node) {
|
|
1218
|
-
references.push(currentNode);
|
|
1219
|
-
}
|
|
1220
|
-
}
|
|
1221
|
-
|
|
1222
|
-
// 深度优先遍历所有子节点
|
|
1223
|
-
var stack = [currentNode];
|
|
1224
|
-
|
|
1225
|
-
while (stack.length > 0) {
|
|
1226
|
-
var current = stack.pop();
|
|
1227
|
-
|
|
1228
|
-
// 遍历当前节点的所有属性
|
|
1229
|
-
Object.keys(current).forEach(function(key) {
|
|
1230
|
-
// 跳过可能引起循环的属性
|
|
1231
|
-
if (key === 'parent' || key === 'range' || key === 'loc' || key === 'comments') {
|
|
1232
|
-
return;
|
|
1233
|
-
}
|
|
1234
|
-
|
|
1235
|
-
var child = current[key];
|
|
1236
|
-
|
|
1237
|
-
if (child && typeof child === 'object') {
|
|
1238
|
-
if (Array.isArray(child)) {
|
|
1239
|
-
// 将数组元素逆序压入栈中,保持遍历顺序
|
|
1240
|
-
for (var i = child.length - 1; i >= 0; i--) {
|
|
1241
|
-
var item = child[i];
|
|
1242
|
-
if (item && typeof item === 'object' && !visited.has(item)) {
|
|
1243
|
-
visited.add(item);
|
|
1244
|
-
|
|
1245
|
-
// 检查是否为标识符节点
|
|
1246
|
-
if (item.type === 'Identifier' && item.name === oldName && item !== fix_info.param_node) {
|
|
1247
|
-
references.push(item);
|
|
1248
|
-
}
|
|
1249
|
-
|
|
1250
|
-
stack.push(item);
|
|
1251
|
-
}
|
|
1252
|
-
}
|
|
1253
|
-
} else if (!visited.has(child)) {
|
|
1254
|
-
visited.add(child);
|
|
1255
|
-
|
|
1256
|
-
// 检查是否为标识符节点
|
|
1257
|
-
if (child.type === 'Identifier' && child.name === oldName && child !== fix_info.param_node) {
|
|
1258
|
-
references.push(child);
|
|
1259
|
-
}
|
|
1260
|
-
|
|
1261
|
-
stack.push(child);
|
|
1262
|
-
}
|
|
1263
|
-
}
|
|
1264
|
-
});
|
|
1265
|
-
}
|
|
1266
|
-
}
|
|
1267
|
-
|
|
1268
|
-
traverse(astNode);
|
|
1269
|
-
return references;
|
|
1270
|
-
}
|
|
1271
|
-
|
|
1272
|
-
// 查找函数体内的所有引用
|
|
1273
|
-
var references = findIdentifierReferences(node.body, fix_info.old_name);
|
|
1274
|
-
|
|
1275
|
-
// 如果找到引用,创建一个包含所有修复的单一修复函数
|
|
1276
|
-
if (references.length > 0) {
|
|
1277
|
-
context.report({
|
|
1278
|
-
node: node,
|
|
1279
|
-
message: '参数引用不一致:' + fix_info.old_name + ' 应该使用 ' + fix_info.new_name + ' (找到 ' + references.length + ' 个引用)',
|
|
1280
|
-
fix: function(fixer) {
|
|
1281
|
-
var fixes = [];
|
|
1282
|
-
|
|
1283
|
-
// 为每个引用添加修复
|
|
1284
|
-
references.forEach(function(refNode) {
|
|
1285
|
-
fixes.push(fixer.replaceText(refNode, fix_info.new_name));
|
|
1286
|
-
});
|
|
1287
|
-
|
|
1288
|
-
// 返回所有修复的数组
|
|
1289
|
-
return fixes;
|
|
1290
|
-
}
|
|
1291
|
-
});
|
|
1292
|
-
}
|
|
339
|
+
function createNamingRules() {
|
|
340
|
+
var rules = new Rules();
|
|
341
|
+
return rules.getAllRules();
|
|
1293
342
|
}
|
|
1294
343
|
|
|
1295
|
-
module.exports =
|
|
1296
|
-
rules: createNamingRules(),
|
|
1297
|
-
};
|
|
344
|
+
module.exports = createNamingRules();
|