mm_eslint 1.4.1 → 1.4.2
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/config.js +78 -44
- package/detector.js +2341 -369
- package/index.js +977 -77
- package/package.json +1 -1
- package/README_EN.md +0 -410
package/index.js
CHANGED
|
@@ -14,6 +14,75 @@ function createNamingRules() {
|
|
|
14
14
|
var config = new Config({});
|
|
15
15
|
var detector = new Detector(config);
|
|
16
16
|
|
|
17
|
+
/**
|
|
18
|
+
* 检查节点是否为参数名或参数引用
|
|
19
|
+
* @param {object} node AST节点
|
|
20
|
+
* @returns {boolean} 是否为参数名或参数引用
|
|
21
|
+
*/
|
|
22
|
+
function _isParameterName(node) {
|
|
23
|
+
if (!node || !node.parent) {
|
|
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;
|
|
84
|
+
}
|
|
85
|
+
|
|
17
86
|
return {
|
|
18
87
|
'class-name': {
|
|
19
88
|
meta: {
|
|
@@ -23,6 +92,7 @@ function createNamingRules() {
|
|
|
23
92
|
category: 'Stylistic Issues',
|
|
24
93
|
recommended: true,
|
|
25
94
|
},
|
|
95
|
+
fixable: 'code',
|
|
26
96
|
schema: [],
|
|
27
97
|
},
|
|
28
98
|
create: function (context) {
|
|
@@ -31,10 +101,23 @@ function createNamingRules() {
|
|
|
31
101
|
var class_name = node.id.name;
|
|
32
102
|
var err = detector._checkClassName(class_name, node);
|
|
33
103
|
if (err) {
|
|
34
|
-
|
|
104
|
+
// 获取修复建议
|
|
105
|
+
var fix_suggestion = detector._getFixSuggestion(class_name, 'class-name', err.message);
|
|
106
|
+
|
|
107
|
+
var report_obj = {
|
|
35
108
|
node: err.node,
|
|
36
109
|
message: err.message,
|
|
37
|
-
}
|
|
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);
|
|
38
121
|
}
|
|
39
122
|
},
|
|
40
123
|
};
|
|
@@ -49,6 +132,7 @@ function createNamingRules() {
|
|
|
49
132
|
category: 'Stylistic Issues',
|
|
50
133
|
recommended: true,
|
|
51
134
|
},
|
|
135
|
+
fixable: 'code',
|
|
52
136
|
schema: [],
|
|
53
137
|
},
|
|
54
138
|
create: function (context) {
|
|
@@ -58,10 +142,26 @@ function createNamingRules() {
|
|
|
58
142
|
var function_name = node.id.name;
|
|
59
143
|
var err = detector._checkFunctionName(function_name, node);
|
|
60
144
|
if (err) {
|
|
61
|
-
|
|
145
|
+
// 获取修复建议
|
|
146
|
+
var fix_suggestion = detector._getFixSuggestion(function_name, 'function-name', err.message);
|
|
147
|
+
|
|
148
|
+
var report_obj = {
|
|
62
149
|
node: err.node,
|
|
63
150
|
message: err.message,
|
|
64
|
-
}
|
|
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);
|
|
65
165
|
}
|
|
66
166
|
}
|
|
67
167
|
},
|
|
@@ -70,10 +170,90 @@ function createNamingRules() {
|
|
|
70
170
|
var function_name = node.id.name;
|
|
71
171
|
var err = detector._checkFunctionName(function_name, node);
|
|
72
172
|
if (err) {
|
|
73
|
-
|
|
173
|
+
// 获取修复建议
|
|
174
|
+
var fix_suggestion = detector._getFixSuggestion(function_name, 'function-name', err.message);
|
|
175
|
+
|
|
176
|
+
var report_obj = {
|
|
74
177
|
node: err.node,
|
|
75
178
|
message: err.message,
|
|
76
|
-
}
|
|
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
|
+
}
|
|
195
|
+
},
|
|
196
|
+
};
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
|
|
200
|
+
'function-call-name': {
|
|
201
|
+
meta: {
|
|
202
|
+
type: 'suggestion',
|
|
203
|
+
docs: {
|
|
204
|
+
description: '检测函数调用名是否符合命名规范',
|
|
205
|
+
category: 'Stylistic Issues',
|
|
206
|
+
recommended: true,
|
|
207
|
+
},
|
|
208
|
+
fixable: 'code',
|
|
209
|
+
schema: [],
|
|
210
|
+
},
|
|
211
|
+
create: function (context) {
|
|
212
|
+
var self = this;
|
|
213
|
+
|
|
214
|
+
return {
|
|
215
|
+
CallExpression: function (node) {
|
|
216
|
+
if (node.callee && node.callee.type === 'Identifier') {
|
|
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);
|
|
77
257
|
}
|
|
78
258
|
}
|
|
79
259
|
},
|
|
@@ -89,6 +269,7 @@ function createNamingRules() {
|
|
|
89
269
|
category: 'Stylistic Issues',
|
|
90
270
|
recommended: true,
|
|
91
271
|
},
|
|
272
|
+
fixable: 'code',
|
|
92
273
|
schema: [],
|
|
93
274
|
},
|
|
94
275
|
create: function (context) {
|
|
@@ -98,10 +279,113 @@ function createNamingRules() {
|
|
|
98
279
|
var method_name = node.key.name;
|
|
99
280
|
var err = detector._checkMethodName(method_name, node);
|
|
100
281
|
if (err) {
|
|
101
|
-
|
|
282
|
+
// 获取修复建议
|
|
283
|
+
var fix_suggestion = detector._getFixSuggestion(method_name, 'method-name', err.message);
|
|
284
|
+
|
|
285
|
+
var report_obj = {
|
|
102
286
|
node: err.node,
|
|
103
287
|
message: err.message,
|
|
104
|
-
}
|
|
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
|
+
}
|
|
304
|
+
},
|
|
305
|
+
|
|
306
|
+
// 处理原型方法定义:ClassName.prototype.method_name = function() {}
|
|
307
|
+
AssignmentExpression: function (node) {
|
|
308
|
+
if (node.left &&
|
|
309
|
+
node.left.type === 'MemberExpression' &&
|
|
310
|
+
node.left.object &&
|
|
311
|
+
node.left.object.type === 'MemberExpression' &&
|
|
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);
|
|
105
389
|
}
|
|
106
390
|
}
|
|
107
391
|
},
|
|
@@ -117,6 +401,7 @@ function createNamingRules() {
|
|
|
117
401
|
category: 'Stylistic Issues',
|
|
118
402
|
recommended: true,
|
|
119
403
|
},
|
|
404
|
+
fixable: 'code',
|
|
120
405
|
schema: [],
|
|
121
406
|
},
|
|
122
407
|
create: function (context) {
|
|
@@ -130,10 +415,23 @@ function createNamingRules() {
|
|
|
130
415
|
var variable_name = decl.id.name;
|
|
131
416
|
var err = detector._checkVariableName(variable_name, decl);
|
|
132
417
|
if (err) {
|
|
133
|
-
|
|
418
|
+
// 获取修复建议
|
|
419
|
+
var fix_suggestion = detector._getFixSuggestion(variable_name, 'variable-name', err.message);
|
|
420
|
+
|
|
421
|
+
var report_obj = {
|
|
134
422
|
node: decl.id,
|
|
135
423
|
message: err.message,
|
|
136
|
-
}
|
|
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);
|
|
137
435
|
}
|
|
138
436
|
}
|
|
139
437
|
// 处理解构赋值 - ObjectPattern
|
|
@@ -143,10 +441,23 @@ function createNamingRules() {
|
|
|
143
441
|
var variable_name = property.key.name;
|
|
144
442
|
var err = detector._checkVariableName(variable_name, decl);
|
|
145
443
|
if (err) {
|
|
146
|
-
|
|
444
|
+
// 获取修复建议
|
|
445
|
+
var fix_suggestion = detector._getFixSuggestion(variable_name, 'variable-name', err.message);
|
|
446
|
+
|
|
447
|
+
var report_obj = {
|
|
147
448
|
node: property.key,
|
|
148
449
|
message: err.message,
|
|
149
|
-
}
|
|
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);
|
|
150
461
|
}
|
|
151
462
|
}
|
|
152
463
|
});
|
|
@@ -158,10 +469,23 @@ function createNamingRules() {
|
|
|
158
469
|
var variable_name = element.name;
|
|
159
470
|
var err = detector._checkVariableName(variable_name, decl);
|
|
160
471
|
if (err) {
|
|
161
|
-
|
|
472
|
+
// 获取修复建议
|
|
473
|
+
var fix_suggestion = detector._getFixSuggestion(variable_name, 'variable-name', err.message);
|
|
474
|
+
|
|
475
|
+
var report_obj = {
|
|
162
476
|
node: element,
|
|
163
477
|
message: err.message,
|
|
164
|
-
}
|
|
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);
|
|
165
489
|
}
|
|
166
490
|
}
|
|
167
491
|
});
|
|
@@ -181,60 +505,19 @@ function createNamingRules() {
|
|
|
181
505
|
category: 'Stylistic Issues',
|
|
182
506
|
recommended: true,
|
|
183
507
|
},
|
|
508
|
+
fixable: 'code',
|
|
184
509
|
schema: [],
|
|
185
510
|
},
|
|
186
511
|
create: function (context) {
|
|
187
512
|
return {
|
|
188
513
|
FunctionDeclaration: function (node) {
|
|
189
|
-
|
|
190
|
-
for (var i = 0; i < node.params.length; i++) {
|
|
191
|
-
var param = node.params[i];
|
|
192
|
-
if (param.name) {
|
|
193
|
-
var param_name = param.name;
|
|
194
|
-
var err = detector._checkParamName(param_name, param);
|
|
195
|
-
if (err) {
|
|
196
|
-
context.report({
|
|
197
|
-
node: err.node,
|
|
198
|
-
message: err.message,
|
|
199
|
-
});
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
514
|
+
_fixParamAndReferences(context, node, detector);
|
|
204
515
|
},
|
|
205
516
|
FunctionExpression: function (node) {
|
|
206
|
-
|
|
207
|
-
for (var i = 0; i < node.params.length; i++) {
|
|
208
|
-
var param = node.params[i];
|
|
209
|
-
if (param.name) {
|
|
210
|
-
var param_name = param.name;
|
|
211
|
-
var err = detector._checkParamName(param_name, param);
|
|
212
|
-
if (err) {
|
|
213
|
-
context.report({
|
|
214
|
-
node: err.node,
|
|
215
|
-
message: err.message,
|
|
216
|
-
});
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
}
|
|
517
|
+
_fixParamAndReferences(context, node, detector);
|
|
221
518
|
},
|
|
222
519
|
ArrowFunctionExpression: function (node) {
|
|
223
|
-
|
|
224
|
-
for (var i = 0; i < node.params.length; i++) {
|
|
225
|
-
var param = node.params[i];
|
|
226
|
-
if (param.name) {
|
|
227
|
-
var param_name = param.name;
|
|
228
|
-
var err = detector._checkParamName(param_name, param);
|
|
229
|
-
if (err) {
|
|
230
|
-
context.report({
|
|
231
|
-
node: err.node,
|
|
232
|
-
message: err.message,
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
}
|
|
520
|
+
_fixParamAndReferences(context, node, detector);
|
|
238
521
|
},
|
|
239
522
|
};
|
|
240
523
|
},
|
|
@@ -248,6 +531,7 @@ function createNamingRules() {
|
|
|
248
531
|
category: 'Stylistic Issues',
|
|
249
532
|
recommended: true,
|
|
250
533
|
},
|
|
534
|
+
fixable: 'code',
|
|
251
535
|
schema: [],
|
|
252
536
|
},
|
|
253
537
|
create: function (context) {
|
|
@@ -260,10 +544,60 @@ function createNamingRules() {
|
|
|
260
544
|
var constant_name = decl.id.name;
|
|
261
545
|
var err = detector._checkConstantName(constant_name, decl, decl.init);
|
|
262
546
|
if (err) {
|
|
263
|
-
|
|
547
|
+
var report_obj = {
|
|
264
548
|
node: decl.id,
|
|
265
549
|
message: err.message,
|
|
266
|
-
}
|
|
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);
|
|
267
601
|
}
|
|
268
602
|
}
|
|
269
603
|
// 处理解构赋值 - ObjectPattern
|
|
@@ -274,10 +608,49 @@ function createNamingRules() {
|
|
|
274
608
|
// 对于解构赋值,使用专门的检测方法
|
|
275
609
|
var err = detector._checkConstantNameForDestructuring(constant_name, property.key);
|
|
276
610
|
if (err) {
|
|
277
|
-
|
|
611
|
+
var report_obj = {
|
|
278
612
|
node: property.key,
|
|
279
613
|
message: err.message,
|
|
280
|
-
}
|
|
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);
|
|
281
654
|
}
|
|
282
655
|
}
|
|
283
656
|
});
|
|
@@ -290,10 +663,37 @@ function createNamingRules() {
|
|
|
290
663
|
// 对于解构赋值,使用专门的检测方法
|
|
291
664
|
var err = detector._checkConstantNameForDestructuring(constant_name, element);
|
|
292
665
|
if (err) {
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
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);
|
|
297
697
|
}
|
|
298
698
|
}
|
|
299
699
|
});
|
|
@@ -305,15 +705,16 @@ function createNamingRules() {
|
|
|
305
705
|
},
|
|
306
706
|
},
|
|
307
707
|
|
|
308
|
-
'property-name': {
|
|
708
|
+
'property-value-name': {
|
|
309
709
|
meta: {
|
|
310
710
|
type: 'suggestion',
|
|
311
711
|
docs: {
|
|
312
|
-
description: '
|
|
712
|
+
description: '属性值名命名规范检测',
|
|
313
713
|
category: 'Stylistic Issues',
|
|
314
|
-
recommended: true
|
|
714
|
+
recommended: true
|
|
315
715
|
},
|
|
316
|
-
|
|
716
|
+
fixable: 'code',
|
|
717
|
+
schema: []
|
|
317
718
|
},
|
|
318
719
|
create: function (context) {
|
|
319
720
|
return {
|
|
@@ -344,14 +745,83 @@ function createNamingRules() {
|
|
|
344
745
|
parent_info,
|
|
345
746
|
);
|
|
346
747
|
|
|
347
|
-
|
|
348
|
-
|
|
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 = {
|
|
349
754
|
node: err.node,
|
|
350
755
|
message: err.message,
|
|
351
|
-
}
|
|
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);
|
|
352
767
|
}
|
|
353
768
|
}
|
|
354
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
|
+
}
|
|
823
|
+
},
|
|
824
|
+
// 检测普通属性赋值,排除原型方法
|
|
355
825
|
AssignmentExpression: function (node) {
|
|
356
826
|
if (
|
|
357
827
|
node.left &&
|
|
@@ -359,6 +829,20 @@ function createNamingRules() {
|
|
|
359
829
|
node.left.property &&
|
|
360
830
|
node.left.property.name
|
|
361
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
|
+
|
|
362
846
|
var prop_name = node.left.property.name;
|
|
363
847
|
|
|
364
848
|
// 直接跳过null值和未赋值属性的检测
|
|
@@ -378,20 +862,436 @@ function createNamingRules() {
|
|
|
378
862
|
node.parent,
|
|
379
863
|
);
|
|
380
864
|
|
|
381
|
-
|
|
382
|
-
|
|
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 = {
|
|
383
871
|
node: err.node,
|
|
384
872
|
message: err.message,
|
|
385
|
-
}
|
|
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);
|
|
386
884
|
}
|
|
387
885
|
}
|
|
388
886
|
},
|
|
389
887
|
};
|
|
390
888
|
},
|
|
391
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
|
+
}
|
|
942
|
+
},
|
|
943
|
+
};
|
|
944
|
+
},
|
|
945
|
+
},
|
|
946
|
+
|
|
947
|
+
'property-class-name': {
|
|
948
|
+
meta: {
|
|
949
|
+
type: 'suggestion',
|
|
950
|
+
docs: {
|
|
951
|
+
description: '属性类名命名规范检测',
|
|
952
|
+
category: 'Stylistic Issues',
|
|
953
|
+
recommended: true
|
|
954
|
+
},
|
|
955
|
+
fixable: 'code',
|
|
956
|
+
schema: []
|
|
957
|
+
},
|
|
958
|
+
create: function (context) {
|
|
959
|
+
return {
|
|
960
|
+
Property: function (node) {
|
|
961
|
+
if (node.key && node.key.name) {
|
|
962
|
+
var prop_name = node.key.name;
|
|
963
|
+
|
|
964
|
+
// 传递祖父节点信息,用于第三方库排除检测
|
|
965
|
+
var parent_info = {
|
|
966
|
+
node: node.parent,
|
|
967
|
+
parent: node.parent ? node.parent.parent : null
|
|
968
|
+
};
|
|
969
|
+
|
|
970
|
+
var err = detector._checkPropertyName(
|
|
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;
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
context.report(report_obj);
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
},
|
|
999
|
+
};
|
|
1000
|
+
},
|
|
1001
|
+
},
|
|
1002
|
+
|
|
1003
|
+
'property-instance-class-name': {
|
|
1004
|
+
meta: {
|
|
1005
|
+
type: 'suggestion',
|
|
1006
|
+
docs: {
|
|
1007
|
+
description: '属性实例类名命名规范检测',
|
|
1008
|
+
category: 'Stylistic Issues',
|
|
1009
|
+
recommended: true
|
|
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;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
context.report(report_obj);
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
},
|
|
1057
|
+
|
|
1058
|
+
// 检测类实例属性中的属性实例类名 (this.xxx)
|
|
1059
|
+
AssignmentExpression: function (node) {
|
|
1060
|
+
// 检查是否是 this.xxx = value 形式的赋值
|
|
1061
|
+
if (node.left && node.left.type === 'MemberExpression' &&
|
|
1062
|
+
node.left.object && node.left.object.type === 'ThisExpression' &&
|
|
1063
|
+
node.left.property && node.left.property.type === 'Identifier') {
|
|
1064
|
+
|
|
1065
|
+
// 排除类实例方法:this.method_name = function() {}
|
|
1066
|
+
var is_instance_method =
|
|
1067
|
+
node.right &&
|
|
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;
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
context.report(report_obj);
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
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
|
+
},
|
|
1138
|
+
};
|
|
1139
|
+
},
|
|
1140
|
+
},
|
|
392
1141
|
};
|
|
393
1142
|
}
|
|
394
1143
|
|
|
1144
|
+
/**
|
|
1145
|
+
* 修复参数声明和所有相关引用
|
|
1146
|
+
* @param {object} context ESLint上下文
|
|
1147
|
+
* @param {object} node 函数节点
|
|
1148
|
+
* @param {object} detector 检测器实例
|
|
1149
|
+
*/
|
|
1150
|
+
function _fixParamAndReferences(context, node, detector) {
|
|
1151
|
+
if (!node.params || !node.body) return;
|
|
1152
|
+
|
|
1153
|
+
// 收集需要修复的参数映射
|
|
1154
|
+
var param_fixes = [];
|
|
1155
|
+
|
|
1156
|
+
node.params.forEach(function(param) {
|
|
1157
|
+
if (param.name) {
|
|
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
|
+
});
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
/**
|
|
1194
|
+
* 检查并修复参数引用不一致问题
|
|
1195
|
+
* @param {object} context ESLint上下文
|
|
1196
|
+
* @param {object} node 函数节点
|
|
1197
|
+
* @param {object} fix_info 修复信息
|
|
1198
|
+
*/
|
|
1199
|
+
function _checkParamReferenceInconsistencies(context, node, fix_info) {
|
|
1200
|
+
var source_code = context.getSourceCode();
|
|
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
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
|
|
395
1295
|
module.exports = {
|
|
396
1296
|
rules: createNamingRules(),
|
|
397
1297
|
};
|