mm_eslint 1.6.0 → 1.6.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/lib/config.js +0 -1
- package/lib/detector/function_name.js +139 -0
- package/lib/detector/name.js +70 -0
- package/lib/validator.js +26 -1
- package/package.json +1 -1
package/lib/config.js
CHANGED
|
@@ -262,6 +262,11 @@ FunctionName.prototype.CallExpression = function (node) {
|
|
|
262
262
|
return undefined;
|
|
263
263
|
}
|
|
264
264
|
|
|
265
|
+
// 检查是否为导入的函数或第三方库函数
|
|
266
|
+
if (this._isExternalFunction(node, name)) {
|
|
267
|
+
return undefined;
|
|
268
|
+
}
|
|
269
|
+
|
|
265
270
|
let original_type = 'use-function';
|
|
266
271
|
let error = this.check(node, name, original_type);
|
|
267
272
|
this.report(node, error, original_type);
|
|
@@ -281,6 +286,19 @@ FunctionName.prototype.CallExpression = function (node) {
|
|
|
281
286
|
return undefined;
|
|
282
287
|
}
|
|
283
288
|
|
|
289
|
+
// 检查是否为 this. 开头的函数调用,如果是则直接检测(通常是自定义函数)
|
|
290
|
+
if (callee.object && callee.object.type === 'ThisExpression') {
|
|
291
|
+
let original_type = 'use-function';
|
|
292
|
+
let error = this.check(callee.property, name, original_type);
|
|
293
|
+
this.report(callee.property, error, original_type);
|
|
294
|
+
return error;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// 检查是否为导入的函数或第三方库函数
|
|
298
|
+
if (this._isExternalFunction(node, name)) {
|
|
299
|
+
return undefined;
|
|
300
|
+
}
|
|
301
|
+
|
|
284
302
|
let original_type = 'use-function';
|
|
285
303
|
let error = this.check(callee.property, name, original_type);
|
|
286
304
|
this.report(callee.property, error, original_type);
|
|
@@ -366,4 +384,125 @@ FunctionName.prototype.ExportNamedDeclaration = function (node) {
|
|
|
366
384
|
}
|
|
367
385
|
}
|
|
368
386
|
|
|
387
|
+
/**
|
|
388
|
+
* 检查函数是否为外部函数(不在当前作用域内定义的函数)
|
|
389
|
+
* @param {Object} node - 调用表达式节点
|
|
390
|
+
* @param {string} name - 函数名
|
|
391
|
+
* @returns {boolean} - 是否为外部函数
|
|
392
|
+
*/
|
|
393
|
+
FunctionName.prototype._isExternalFunction = function (node, name) {
|
|
394
|
+
if (!name || !node) {
|
|
395
|
+
return false;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// 如果函数在当前作用域内有定义,则不是外部函数
|
|
399
|
+
if (this._isFunctionInScope(name, node)) {
|
|
400
|
+
return false;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// 检查是否为导入的函数(通过 import 或 require)
|
|
404
|
+
if (this._isImportedFunction(name, node)) {
|
|
405
|
+
return true;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// 检查是否为全局对象上的函数(如 console.log, Math.max 等)
|
|
409
|
+
if (this._isGlobalObjectFunction(name, node)) {
|
|
410
|
+
return true;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// 默认情况下,如果函数不在当前作用域内定义,则认为是外部函数
|
|
414
|
+
return true;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* 检查函数是否为导入的函数
|
|
419
|
+
* @param {string} name - 函数名
|
|
420
|
+
* @param {Object} node - 当前节点
|
|
421
|
+
* @returns {boolean} - 是否为导入的函数
|
|
422
|
+
*/
|
|
423
|
+
FunctionName.prototype._isImportedFunction = function (name, node) {
|
|
424
|
+
if (!name || !node) {
|
|
425
|
+
return false;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// 获取AST根节点
|
|
429
|
+
let program_node = this._getProgramNode(node);
|
|
430
|
+
if (!program_node || !program_node.body) {
|
|
431
|
+
return false;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// 遍历同级节点查找导入声明
|
|
435
|
+
for (let i = 0; i < program_node.body.length; i++) {
|
|
436
|
+
let sibling_node = program_node.body[i];
|
|
437
|
+
|
|
438
|
+
// 检查ES6导入声明
|
|
439
|
+
if (sibling_node.type === 'ImportDeclaration') {
|
|
440
|
+
if (sibling_node.specifiers && sibling_node.specifiers.length > 0) {
|
|
441
|
+
for (let j = 0; j < sibling_node.specifiers.length; j++) {
|
|
442
|
+
let specifier = sibling_node.specifiers[j];
|
|
443
|
+
|
|
444
|
+
// 检查导入的标识符名称
|
|
445
|
+
if (specifier.local && specifier.local.type === 'Identifier' && specifier.local.name === name) {
|
|
446
|
+
return true;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// 检查CommonJS require导入
|
|
453
|
+
if (sibling_node.type === 'VariableDeclaration') {
|
|
454
|
+
for (let j = 0; j < sibling_node.declarations.length; j++) {
|
|
455
|
+
let decl = sibling_node.declarations[j];
|
|
456
|
+
if (decl.id && decl.id.type === 'Identifier' && decl.id.name === name) {
|
|
457
|
+
// 检查是否为require调用
|
|
458
|
+
if (decl.init && decl.init.type === 'CallExpression' &&
|
|
459
|
+
decl.init.callee && decl.init.callee.type === 'Identifier' &&
|
|
460
|
+
decl.init.callee.name === 'require') {
|
|
461
|
+
return true;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
return false;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* 检查函数是否为全局对象上的函数
|
|
473
|
+
* @param {string} name - 函数名
|
|
474
|
+
* @param {Object} node - 当前节点
|
|
475
|
+
* @returns {boolean} - 是否为全局对象函数
|
|
476
|
+
*/
|
|
477
|
+
FunctionName.prototype._isGlobalObjectFunction = function (name, node) {
|
|
478
|
+
if (!name) {
|
|
479
|
+
return false;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
// 常见的全局对象函数列表
|
|
483
|
+
const global_object_functions = [
|
|
484
|
+
// console 对象
|
|
485
|
+
'log', 'info', 'warn', 'error', 'debug', 'table', 'time', 'timeEnd',
|
|
486
|
+
// Math 对象
|
|
487
|
+
'abs', 'ceil', 'floor', 'round', 'max', 'min', 'pow', 'sqrt', 'random',
|
|
488
|
+
// JSON 对象
|
|
489
|
+
'parse', 'stringify',
|
|
490
|
+
// Object 对象
|
|
491
|
+
'keys', 'values', 'entries', 'assign', 'create', 'freeze', 'seal',
|
|
492
|
+
// Array 对象
|
|
493
|
+
'isArray', 'from', 'of',
|
|
494
|
+
// String 对象
|
|
495
|
+
'fromCharCode', 'fromCodePoint',
|
|
496
|
+
// Number 对象
|
|
497
|
+
'isFinite', 'isInteger', 'isNaN', 'isSafeInteger', 'parseFloat', 'parseInt',
|
|
498
|
+
// Date 对象
|
|
499
|
+
'now', 'parse', 'UTC',
|
|
500
|
+
// RegExp 对象
|
|
501
|
+
'test', 'exec'
|
|
502
|
+
];
|
|
503
|
+
|
|
504
|
+
// 检查是否为全局对象函数
|
|
505
|
+
return global_object_functions.includes(name);
|
|
506
|
+
}
|
|
507
|
+
|
|
369
508
|
module.exports = { FunctionName }
|
package/lib/detector/name.js
CHANGED
|
@@ -197,6 +197,69 @@ Name.prototype._isClassInScope = function (name, node) {
|
|
|
197
197
|
return false;
|
|
198
198
|
}
|
|
199
199
|
|
|
200
|
+
/**
|
|
201
|
+
* 检查类声明中是否包含指定名称的方法
|
|
202
|
+
* @param {Object} class_node - 类声明节点
|
|
203
|
+
* @param {string} name - 方法名
|
|
204
|
+
* @returns {boolean} - 是否包含该方法
|
|
205
|
+
*/
|
|
206
|
+
Name.prototype._isFunctionInClass = function (class_node, name) {
|
|
207
|
+
if (!class_node || !class_node.body || !class_node.body.body) {
|
|
208
|
+
return false;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// 遍历类体中的方法定义
|
|
212
|
+
for (let i = 0; i < class_node.body.body.length; i++) {
|
|
213
|
+
let method_node = class_node.body.body[i];
|
|
214
|
+
|
|
215
|
+
// 检查方法定义(MethodDefinition)
|
|
216
|
+
if (method_node.type === 'MethodDefinition') {
|
|
217
|
+
if (method_node.key && method_node.key.type === 'Identifier' && method_node.key.name === name) {
|
|
218
|
+
return true;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// 检查类属性中的函数赋值(PropertyDefinition)
|
|
223
|
+
if (method_node.type === 'PropertyDefinition') {
|
|
224
|
+
if (method_node.key && method_node.key.type === 'Identifier' && method_node.key.name === name) {
|
|
225
|
+
// 检查属性值是否为函数表达式
|
|
226
|
+
if (method_node.value && (method_node.value.type === 'FunctionExpression' || method_node.value.type === 'ArrowFunctionExpression')) {
|
|
227
|
+
return true;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// 检查构造函数中的方法赋值
|
|
233
|
+
if (method_node.type === 'MethodDefinition' && method_node.kind === 'constructor') {
|
|
234
|
+
if (method_node.value && method_node.value.body && method_node.value.body.body) {
|
|
235
|
+
// 遍历构造函数体中的语句
|
|
236
|
+
for (let j = 0; j < method_node.value.body.body.length; j++) {
|
|
237
|
+
let statement = method_node.value.body.body[j];
|
|
238
|
+
|
|
239
|
+
// 检查 this.property = function() {} 形式的赋值
|
|
240
|
+
if (statement.type === 'ExpressionStatement' && statement.expression && statement.expression.type === 'AssignmentExpression') {
|
|
241
|
+
let expr = statement.expression;
|
|
242
|
+
|
|
243
|
+
// 检查左边是否为 this.propertyName 形式
|
|
244
|
+
if (expr.left && expr.left.type === 'MemberExpression' &&
|
|
245
|
+
expr.left.object && expr.left.object.type === 'ThisExpression' &&
|
|
246
|
+
expr.left.property && expr.left.property.type === 'Identifier' &&
|
|
247
|
+
expr.left.property.name === name) {
|
|
248
|
+
|
|
249
|
+
// 检查右边是否为函数表达式
|
|
250
|
+
if (expr.right && (expr.right.type === 'FunctionExpression' || expr.right.type === 'ArrowFunctionExpression')) {
|
|
251
|
+
return true;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
|
|
200
263
|
/**
|
|
201
264
|
* 检查标识符是否在作用域内定义为函数
|
|
202
265
|
* @param {string} name - 标识符名称
|
|
@@ -242,6 +305,13 @@ Name.prototype._isFunctionInScope = function (name, node) {
|
|
|
242
305
|
}
|
|
243
306
|
}
|
|
244
307
|
}
|
|
308
|
+
|
|
309
|
+
// 查找类声明中的方法定义
|
|
310
|
+
if (sibling_node.type === 'ClassDeclaration') {
|
|
311
|
+
if (this._isFunctionInClass(sibling_node, name)) {
|
|
312
|
+
return true;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
245
315
|
}
|
|
246
316
|
|
|
247
317
|
return false;
|
package/lib/validator.js
CHANGED
|
@@ -84,7 +84,9 @@ Validator.prototype.check = function (name, words, rule) {
|
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
// 检查每个单词的长度, 警告级。
|
|
87
|
-
|
|
87
|
+
// 长度检测前过滤掉忽略词
|
|
88
|
+
var ws = this._filterIgnoreWords(words, rule.ignore_words);
|
|
89
|
+
var word_error = this._validateWordLength(ws, rule.single_word_len);
|
|
88
90
|
if (word_error) {
|
|
89
91
|
return word_error;
|
|
90
92
|
}
|
|
@@ -96,6 +98,29 @@ Validator.prototype.check = function (name, words, rule) {
|
|
|
96
98
|
}
|
|
97
99
|
}
|
|
98
100
|
|
|
101
|
+
/**
|
|
102
|
+
* 过滤掉忽略词
|
|
103
|
+
* @param {array} words 单词数组
|
|
104
|
+
* @param {array} ignore_words 忽略词数组
|
|
105
|
+
* @returns {array} 过滤后的单词数组
|
|
106
|
+
*/
|
|
107
|
+
Validator.prototype._filterIgnoreWords = function (words, ignore_words) {
|
|
108
|
+
if (!words || words.length === 0) {
|
|
109
|
+
return [];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (!ignore_words || ignore_words.length === 0) {
|
|
113
|
+
return words;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// 过滤掉忽略词
|
|
117
|
+
var ws = words.filter((word) => {
|
|
118
|
+
return !this._isIgnoreWord(word, ignore_words);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
return ws;
|
|
122
|
+
}
|
|
123
|
+
|
|
99
124
|
/**
|
|
100
125
|
* 判断名称是否为忽略词
|
|
101
126
|
* @param {string} name 名称
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mm_eslint",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.2",
|
|
4
4
|
"description": "ESLint plugin for personal naming conventions - supports PascalCase, camelCase, snake_case, and UPPER_SNAKE_CASE naming rules with intelligent recommendations",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"keywords": [
|