mm_eslint 1.2.7 → 1.2.8

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.
Files changed (3) hide show
  1. package/config.js +523 -0
  2. package/detector.js +998 -0
  3. package/package.json +3 -1
package/detector.js ADDED
@@ -0,0 +1,998 @@
1
+ /**
2
+ * 命名规范检测器类
3
+ */
4
+ class Detector {
5
+ /**
6
+ * 构造函数
7
+ * @param {object} config 配置对象
8
+ */
9
+ constructor(config) {
10
+ // 直接将传入的配置对象赋值,确保原型方法不被丢失
11
+ this.config = config;
12
+
13
+ // 添加命名类型的中文描述
14
+ this.config.name_type_map = {
15
+ 'class-name': '类名',
16
+ 'function-name': '函数名',
17
+ 'method-name': '方法名',
18
+ 'variable-name': '变量名',
19
+ 'param-name': '参数名',
20
+ 'constant-name': '常量名',
21
+ 'property-class-name': '属性类名',
22
+ 'property-instance-class-name': '属性实例类名',
23
+ 'property-method-name': '属性方法名',
24
+ 'property-value-name': '属性值名'
25
+ };
26
+ }
27
+ }
28
+
29
+ /**
30
+ * 检测类名
31
+ * @param {string} class_name 类名
32
+ * @param {object} node AST节点
33
+ * @returns {object|null} 错误信息或null
34
+ */
35
+ Detector.prototype._checkClassName = function (class_name, node) {
36
+ try {
37
+ var rule = this.config.getRule('class-name');
38
+ if (!rule) {
39
+ return null;
40
+ }
41
+
42
+ // 检查是否为忽略词
43
+ if (this._isIgnoredWord(class_name, 'class-name')) {
44
+ return null;
45
+ }
46
+
47
+ // 检查命名风格
48
+ var style_err = this._validate_naming_style(class_name, rule.styles, 'class-name');
49
+ if (style_err) {
50
+ return {
51
+ node: node,
52
+ message: style_err,
53
+ };
54
+ }
55
+
56
+ // 检查并推荐更合适的词汇
57
+ var rec_err = this._checkAndRecommend(class_name, 'class-name');
58
+ if (rec_err) {
59
+ return {
60
+ node: node,
61
+ message: rec_err,
62
+ };
63
+ }
64
+
65
+ // 检查长度
66
+ var len_err = this._checkNameLength(class_name, rule.min, rule.max, 'class-name');
67
+ if (len_err) {
68
+ return {
69
+ node: node,
70
+ message: len_err,
71
+ };
72
+ }
73
+
74
+ // 检查单词长度
75
+ var word_err = this._checkWordLength(class_name, rule.single_word_len, 'class-name');
76
+ if (word_err) {
77
+ return {
78
+ node: node,
79
+ message: word_err,
80
+ };
81
+ }
82
+
83
+ // 检查禁止词汇
84
+ var forbid_err = this._checkForbiddenWords(class_name, 'class-name');
85
+ if (forbid_err) {
86
+ return {
87
+ node: node,
88
+ message: forbid_err,
89
+ };
90
+ }
91
+
92
+ return null;
93
+ } catch (error) {
94
+ console.error('检测类名时出错:', error);
95
+ return null;
96
+ }
97
+ };
98
+
99
+ /**
100
+ * 检测方法名
101
+ * @param {string} method_name 方法名
102
+ * @param {object} node AST节点
103
+ * @returns {object|null} 错误信息或null
104
+ */
105
+ Detector.prototype._checkMethodName = function (method_name, node) {
106
+ try {
107
+ var rule = this.config.getRule('method-name');
108
+ if (!rule) {
109
+ return null;
110
+ }
111
+
112
+ // 检查是否为忽略词(在所有检测之前)
113
+ if (this._isIgnoredWord(method_name, 'method-name')) {
114
+ return null;
115
+ }
116
+
117
+ // 检查命名风格(支持公开方法和私有方法)
118
+ var style_err = null;
119
+ if (method_name.startsWith('_')) {
120
+ // 私有方法:检查是否符合私有方法命名规范
121
+ style_err = this._validate_naming_style(method_name, ['_camelCase'], 'method-name');
122
+ } else {
123
+ // 公开方法:检查是否符合公开方法命名规范
124
+ style_err = this._validate_naming_style(method_name, rule.styles, 'method-name');
125
+ }
126
+
127
+ if (style_err) {
128
+ return {
129
+ node: node,
130
+ message: style_err,
131
+ };
132
+ }
133
+
134
+ // 检查长度
135
+ var len_err = this._checkNameLength(method_name, rule.min, rule.max, 'method-name');
136
+ if (len_err) {
137
+ return {
138
+ node: node,
139
+ message: len_err,
140
+ };
141
+ }
142
+
143
+ // 检查单词长度
144
+ var word_err = this._checkWordLength(method_name, rule.single_word_len, 'method-name');
145
+ if (word_err) {
146
+ return {
147
+ node: node,
148
+ message: word_err,
149
+ };
150
+ }
151
+
152
+ // 检查禁止词汇
153
+ var forbid_err = this._checkForbiddenWords(method_name, 'method-name');
154
+ if (forbid_err) {
155
+ return {
156
+ node: node,
157
+ message: forbid_err,
158
+ };
159
+ }
160
+
161
+ // 检查并推荐更合适的词汇
162
+ var recommend_err = this._checkAndRecommend(method_name, 'method-name');
163
+ if (recommend_err) {
164
+ return {
165
+ node: node,
166
+ message: recommend_err,
167
+ };
168
+ }
169
+
170
+ return null;
171
+ } catch (error) {
172
+ console.error('检测方法名时出错:', error);
173
+ return null;
174
+ }
175
+ };
176
+
177
+ /**
178
+ * 检测函数名
179
+ * @param {string} function_name 函数名
180
+ * @param {object} node AST节点
181
+ * @returns {object|null} 错误信息或null
182
+ */
183
+ Detector.prototype._checkFunctionName = function (function_name, node) {
184
+ try {
185
+ var rule = this.config.getRule('function-name');
186
+ if (!rule) {
187
+ return null;
188
+ }
189
+
190
+ // 检查是否为忽略词
191
+ if (this._isIgnoredWord(function_name, 'function-name')) {
192
+ return null;
193
+ }
194
+
195
+ // 检查命名风格
196
+ var style_err = this._validate_naming_style(function_name, rule.styles, 'function-name');
197
+ if (style_err) {
198
+ return {
199
+ node: node,
200
+ message: style_err,
201
+ };
202
+ }
203
+
204
+ // 检查长度
205
+ var len_err = this._checkNameLength(function_name, rule.min, rule.max, 'function-name');
206
+ if (len_err) {
207
+ return {
208
+ node: node,
209
+ message: len_err,
210
+ };
211
+ }
212
+
213
+ // 检查单词长度
214
+ var word_err = this._checkWordLength(function_name, rule.single_word_len, 'function-name');
215
+ if (word_err) {
216
+ return {
217
+ node: node,
218
+ message: word_err,
219
+ };
220
+ }
221
+
222
+ // 检查禁止词汇
223
+ var forbid_err = this._checkForbiddenWords(
224
+ function_name,
225
+ 'function-name',
226
+ );
227
+ if (forbid_err) {
228
+ return {
229
+ node: node,
230
+ message: forbid_err,
231
+ };
232
+ }
233
+
234
+ // 检查并推荐更合适的词汇
235
+ var recommend_err = this._checkAndRecommend(function_name, 'function-name');
236
+ if (recommend_err) {
237
+ return {
238
+ node: node,
239
+ message: recommend_err,
240
+ };
241
+ }
242
+
243
+ return null;
244
+ } catch (error) {
245
+ console.error('检测函数名时出错:', error);
246
+ return null;
247
+ }
248
+ };
249
+
250
+ /**
251
+ * 检测变量名
252
+ * @param {string} variable_name 变量名
253
+ * @param {object} node AST节点
254
+ * @returns {object|null} 错误信息或null
255
+ */
256
+ Detector.prototype._checkVariableName = function (variable_name, node) {
257
+ try {
258
+ var rule = this.config.getRule('variable-name');
259
+ if (!rule) {
260
+ return null;
261
+ }
262
+
263
+ // 检查是否为忽略词
264
+ if (this._isIgnoredWord(variable_name, 'variable-name')) {
265
+ return null;
266
+ }
267
+
268
+ // 检查命名风格
269
+ var style_err = this._validate_naming_style(variable_name, rule.styles, 'variable-name');
270
+ if (style_err) {
271
+ return {
272
+ node: node,
273
+ message: style_err,
274
+ };
275
+ }
276
+
277
+ // 检查长度
278
+ var len_err = this._checkNameLength(variable_name, rule.min, rule.max, 'variable-name');
279
+ if (len_err) {
280
+ return {
281
+ node: node,
282
+ message: len_err,
283
+ };
284
+ }
285
+
286
+ // 检查单词长度
287
+ var word_err = this._checkWordLength(variable_name, rule.single_word_len, 'variable-name');
288
+ if (word_err) {
289
+ return {
290
+ node: node,
291
+ message: word_err,
292
+ };
293
+ }
294
+
295
+ // 检查禁止词汇
296
+ var forbid_err = this._checkForbiddenWords(
297
+ variable_name,
298
+ 'variable-name',
299
+ );
300
+ if (forbid_err) {
301
+ return {
302
+ node: node,
303
+ message: forbid_err,
304
+ };
305
+ }
306
+
307
+ return null;
308
+ } catch (error) {
309
+ console.error('检测变量名时出错:', error);
310
+ return null;
311
+ }
312
+ };
313
+
314
+ /**
315
+ * 检测参数名
316
+ * @param {string} param_name 参数名
317
+ * @param {object} node AST节点
318
+ * @returns {object|null} 错误信息或null
319
+ */
320
+ Detector.prototype._checkParamName = function (param_name, node) {
321
+ try {
322
+ var rule = this.config.getRule('param-name');
323
+ if (!rule) {
324
+ return null;
325
+ }
326
+
327
+ // 检查是否为忽略词
328
+ if (this._isIgnoredWord(param_name, 'param-name')) {
329
+ return null;
330
+ }
331
+
332
+ // 检查命名风格
333
+ var style_err = this._validate_naming_style(param_name, rule.styles, 'param-name');
334
+ if (style_err) {
335
+ return {
336
+ node: node,
337
+ message: style_err,
338
+ };
339
+ }
340
+
341
+ // 检查长度
342
+ var len_err = this._checkNameLength(param_name, rule.min, rule.max, 'param-name');
343
+ if (len_err) {
344
+ return {
345
+ node: node,
346
+ message: len_err,
347
+ };
348
+ }
349
+
350
+ // 检查单词长度
351
+ var word_err = this._checkWordLength(param_name, rule.single_word_len, 'param-name');
352
+ if (word_err) {
353
+ return {
354
+ node: node,
355
+ message: word_err,
356
+ };
357
+ }
358
+
359
+ // 检查禁止词汇
360
+ var forbid_err = this._checkForbiddenWords(param_name, 'param-name');
361
+ if (forbid_err) {
362
+ return {
363
+ node: node,
364
+ message: forbid_err,
365
+ };
366
+ }
367
+
368
+ return null;
369
+ } catch (error) {
370
+ console.error('检测参数名时出错:', error);
371
+ return null;
372
+ }
373
+ };
374
+
375
+ /**
376
+ * 检测常量名
377
+ * @param {string} constant_name 常量名
378
+ * @param {object} node AST节点
379
+ * @param {object} val_node 值节点(用于识别基础值)
380
+ * @returns {object|null} 错误信息或null
381
+ */
382
+ Detector.prototype._checkConstantName = function (constant_name, node, val_node) {
383
+ try {
384
+ var rule = this.config.getRule('constant-name');
385
+ if (!rule) {
386
+ return null;
387
+ }
388
+
389
+ // 检查是否为忽略词
390
+ if (this._isIgnoredWord(constant_name, 'constant-name')) {
391
+ return null;
392
+ }
393
+
394
+ // 检查是否为复杂类型(方法、函数、实例等)
395
+ var is_complex_type = this._isComplexType(val_node);
396
+
397
+ // 如果是复杂类型,则不进行常量检测
398
+ if (is_complex_type) {
399
+ return null;
400
+ }
401
+
402
+ // 检查是否为基础值类型
403
+ var is_base_value = this._isBaseValue(val_node);
404
+
405
+ // 如果不是基础值也不是复杂类型(可能是其他类型),则不进行常量检测
406
+ if (!is_base_value) {
407
+ return null;
408
+ }
409
+
410
+ // 检查命名风格
411
+ var style_err = this._validate_naming_style(constant_name, rule.styles, 'constant-name');
412
+ if (style_err) {
413
+ return {
414
+ node: node,
415
+ message: style_err,
416
+ };
417
+ }
418
+
419
+ // 检查长度
420
+ var len_err = this._checkNameLength(constant_name, rule.min, rule.max, 'constant-name');
421
+ if (len_err) {
422
+ return {
423
+ node: node,
424
+ message: len_err,
425
+ };
426
+ }
427
+
428
+ // 检查单词长度
429
+ var word_err = this._checkWordLength(constant_name, rule.single_word_len, 'constant-name');
430
+ if (word_err) {
431
+ return {
432
+ node: node,
433
+ message: word_err,
434
+ };
435
+ }
436
+
437
+ // 检查禁止词汇
438
+ var forbid_err = this._checkForbiddenWords(constant_name, 'constant-name');
439
+ if (forbid_err) {
440
+ return {
441
+ node: node,
442
+ message: forbid_err,
443
+ };
444
+ }
445
+
446
+ // 检查并推荐更合适的词汇
447
+ var rec_err = this._checkAndRecommend(constant_name, 'constant-name');
448
+ if (rec_err) {
449
+ return {
450
+ node: node,
451
+ message: rec_err,
452
+ };
453
+ }
454
+
455
+ return null;
456
+ } catch (error) {
457
+ console.error('检测常量名时出错:', error);
458
+ return null;
459
+ }
460
+ };
461
+
462
+ /**
463
+ * 验证命名风格
464
+ * @param {string} name 名称
465
+ * @param {Array} styles 允许的风格列表
466
+ * @param {string} name_type 名称类型
467
+ * @returns {string|null} 错误信息或null
468
+ */
469
+ Detector.prototype._validate_naming_style = function (name, styles, name_type) {
470
+ if (!name || !styles || !Array.isArray(styles)) {
471
+ return null;
472
+ }
473
+
474
+ for (var i = 0; i < styles.length; i++) {
475
+ var style = styles[i];
476
+ var regex = this.config.getRegex(style);
477
+ if (regex && regex.test(name)) {
478
+ return null;
479
+ }
480
+ }
481
+
482
+ var style_names = styles.join('或');
483
+
484
+ var name_type_desc = this.config.name_type_map[name_type] || '名称';
485
+
486
+ return name_type_desc + '\'' + name + '\'不符合' + style_names + '命名风格';
487
+ };
488
+
489
+ /**
490
+ * 检查名称长度
491
+ * @param {string} name 名称
492
+ * @param {number} min 最小长度
493
+ * @param {number} max 最大长度
494
+ * @returns {string|null} 错误信息或null
495
+ */
496
+ Detector.prototype._checkNameLength = function (name, min, max, name_type) {
497
+ if (!name) {
498
+ return '名称不能为空';
499
+ }
500
+
501
+ var name_type_desc = this.config.name_type_map[name_type] || '名称';
502
+ var len = name.length;
503
+ if (len < min) {
504
+ return name_type_desc + '\'' + name + '\'长度过短,最小长度为' + min + '字符';
505
+ }
506
+
507
+ if (len > max) {
508
+ return name_type_desc + '\'' + name + '\'长度过长,最大长度为' + max + '字符';
509
+ }
510
+
511
+ return null;
512
+ };
513
+
514
+ /**
515
+ * 检查单词长度
516
+ * @param {string} name 名称
517
+ * @param {number} max_word_len 最大单词长度
518
+ * @returns {string|null} 错误信息或null
519
+ */
520
+ Detector.prototype._checkWordLength = function (name, max_word_len, name_type) {
521
+ if (!name || !max_word_len) {
522
+ return null;
523
+ }
524
+
525
+ var name_type_desc = this.config.name_type_map[name_type] || '名称';
526
+ // 分割单词(根据命名风格)
527
+ var words = [];
528
+
529
+ // 处理私有标识符(开头的下划线)
530
+ var processed_name = name;
531
+ var has_private_prefix = false;
532
+
533
+ if (name.startsWith('_')) {
534
+ has_private_prefix = true;
535
+ processed_name = name.substring(1); // 去掉开头的下划线
536
+ }
537
+
538
+ if (processed_name.includes('_')) {
539
+ words = processed_name.split('_');
540
+ } else if (processed_name.includes('-')) {
541
+ words = processed_name.split('-');
542
+ } else {
543
+ // 驼峰命名法分割(保持原词大小写)
544
+ words = processed_name.split(/(?=[A-Z])/);
545
+ }
546
+
547
+ // 如果存在私有标识符,添加空字符串表示私有标识符(不检查长度)
548
+ if (has_private_prefix) {
549
+ words.unshift('_');
550
+ }
551
+
552
+ for (var i = 0; i < words.length; i++) {
553
+ var word = words[i];
554
+ // 跳过空字符串和私有标识符(单个下划线)
555
+ if (!word || word === '_') {
556
+ continue;
557
+ }
558
+
559
+ if (word.length > max_word_len) {
560
+ // 生成推荐命名
561
+ var recommended_name = this._generateRecommendedName(name, word, name_type);
562
+ var recommendation_text = '';
563
+ if (recommended_name) {
564
+ recommendation_text = ',推荐名为\'' + recommended_name + '\'';
565
+ }
566
+
567
+ return (
568
+ name_type_desc +
569
+ '\'' +
570
+ name +
571
+ '\'中的单词\'' +
572
+ word +
573
+ '\'过长,最大长度为' +
574
+ max_word_len +
575
+ '字符' +
576
+ recommendation_text
577
+ );
578
+ }
579
+ }
580
+
581
+ return null;
582
+ };
583
+
584
+ /**
585
+ * 检查禁止词汇
586
+ * @param {string} name 名称
587
+ * @param {string} name_type 名称类型
588
+ * @returns {string|null} 错误信息或null
589
+ */
590
+ Detector.prototype._checkForbiddenWords = function (name, name_type) {
591
+ if (!name || !name_type) {
592
+ return null;
593
+ }
594
+
595
+ var forbidden_words = this.config.getForbiddenWords(name_type);
596
+ if (!forbidden_words || !Array.isArray(forbidden_words)) {
597
+ return null;
598
+ }
599
+
600
+ var name_type_desc = this.config.name_type_map[name_type] || '名称';
601
+ var name_lower = name.toLowerCase();
602
+
603
+ // 如果名称本身就是禁止词汇(即单个单词),则允许使用
604
+ for (var i = 0; i < forbidden_words.length; i++) {
605
+ var forbidden_word = forbidden_words[i].toLowerCase();
606
+ if (name_lower === forbidden_word) {
607
+ return null; // 单个单词允许使用
608
+ }
609
+ }
610
+
611
+ // 检查名称是否包含禁止词汇作为拼接词(即名称由多个单词组成)
612
+ for (var i = 0; i < forbidden_words.length; i++) {
613
+ var forbidden_word = forbidden_words[i].toLowerCase();
614
+ if (name_lower.includes(forbidden_word) && name_lower !== forbidden_word) {
615
+ return name_type_desc + '\'' + name + '\'包含禁止拼接词\'' + forbidden_word + '\'';
616
+ }
617
+ }
618
+
619
+ return null;
620
+ };
621
+
622
+ /**
623
+ * 获取属性类型
624
+ * @param {object} val_node 属性值节点
625
+ * @param {string} prop_name 属性名
626
+ * @param {object} parent_node 父节点
627
+ * @returns {string} 属性类型
628
+ */
629
+ Detector.prototype._getPropType = function (val_node, prop_name, parent_node) {
630
+ if (!val_node) {
631
+ return 'undefined_value'; // 未赋值类型
632
+ }
633
+
634
+ // 检查是否为null值
635
+ if (val_node.type === 'NullLiteral') {
636
+ return 'null_value'; // null值类型
637
+ }
638
+
639
+ // 检查是否为对象方法(在对象字面量中的函数)
640
+ if (
641
+ val_node &&
642
+ (val_node.type === 'FunctionExpression' ||
643
+ val_node.type === 'ArrowFunctionExpression')
644
+ ) {
645
+ return 'method'; // 对象方法类型
646
+ }
647
+
648
+ // 检查是否为类引用(属性类)
649
+ if (
650
+ val_node.type === 'Identifier' &&
651
+ val_node.name &&
652
+ val_node.name[0] === val_node.name[0].toUpperCase()
653
+ ) {
654
+ // 检查是否是类名引用(通常类名使用PascalCase)
655
+ return 'class'; // 属性类类型
656
+ }
657
+
658
+ // 检查是否为类实例(new表达式)
659
+ if (val_node.type === 'NewExpression') {
660
+ return 'instance_class'; // 属性实例类类型
661
+ }
662
+
663
+ // 检查是否为函数调用(可能返回实例)
664
+ if (val_node.type === 'CallExpression') {
665
+ // 检查是否调用的是构造函数
666
+ if (
667
+ val_node.callee &&
668
+ val_node.callee.type === 'Identifier' &&
669
+ val_node.callee.name &&
670
+ val_node.callee.name[0] === val_node.callee.name[0].toUpperCase()
671
+ ) {
672
+ return 'instance_class'; // 属性实例类类型
673
+ }
674
+ return 'value'; // 默认值类型
675
+ }
676
+
677
+ return 'value';
678
+ };
679
+
680
+ /**
681
+ * 检测属性名
682
+ * @param {string} prop_name 属性名
683
+ * @param {object} node AST节点
684
+ * @param {object} val_node 属性值节点
685
+ * @param {object} parent_node 父节点
686
+ * @returns {object|null} 错误信息或null
687
+ */
688
+ Detector.prototype._checkPropertyName = function (
689
+ prop_name,
690
+ node,
691
+ val_node,
692
+ parent_node,
693
+ ) {
694
+ try {
695
+ // 获取属性类型
696
+ var prop_type = this._getPropType(val_node, prop_name, parent_node);
697
+ var rule_type = '';
698
+
699
+ // 根据属性类型选择对应的规则
700
+ // 对于null值和未赋值属性,直接跳过命名规范检测
701
+ if (prop_type === 'null_value' || prop_type === 'undefined_value') {
702
+ return null; // 不进行命名规范检测
703
+ }
704
+
705
+ switch (prop_type) {
706
+ case 'class':
707
+ rule_type = 'property-class-name';
708
+ break;
709
+ case 'instance_class':
710
+ rule_type = 'property-instance-class-name';
711
+ break;
712
+ case 'method':
713
+ rule_type = 'property-method-name';
714
+ break;
715
+ case 'value':
716
+ default:
717
+ rule_type = 'property-value-name';
718
+ break;
719
+ }
720
+
721
+ var rule = this.config.getRule(rule_type);
722
+ if (!rule) {
723
+ return null;
724
+ }
725
+
726
+ // 检查命名风格
727
+ var style_err = null;
728
+
729
+ if (rule_type === 'property-value-name') {
730
+ // 对于属性值名,支持私有变量命名规范(_snake_case)、变量命名规范(snake_case)或常量命名规范(UPPER_SNAKE_CASE)
731
+ var private_style_err = this._validate_naming_style(prop_name, ['_snake_case'], rule_type);
732
+ var variable_style_err = this._validate_naming_style(prop_name, ['snake_case'], rule_type);
733
+ var constant_style_err = this._validate_naming_style(prop_name, ['UPPER_SNAKE_CASE'], rule_type);
734
+
735
+ // 只有当所有风格检查都失败时才报错
736
+ if (private_style_err && variable_style_err && constant_style_err) {
737
+ style_err = '属性值名\'' + prop_name + '\'不符合_snake_case、snake_case或UPPER_SNAKE_CASE命名风格';
738
+ }
739
+ } else if (rule_type === 'property-method-name') {
740
+ // 属性方法:支持公开方法(camelCase)和私有方法(_camelCase)
741
+ if (prop_name.startsWith('_')) {
742
+ // 私有方法:检查是否符合私有方法命名规范
743
+ style_err = this._validate_naming_style(prop_name, ['_camelCase'], rule_type);
744
+ } else {
745
+ // 公开方法:检查是否符合公开方法命名规范
746
+ style_err = this._validate_naming_style(prop_name, rule.styles, rule_type);
747
+ }
748
+ } else {
749
+ // 其他属性类型:使用原有逻辑
750
+ style_err = this._validate_naming_style(prop_name, rule.styles, rule_type);
751
+ }
752
+
753
+ if (style_err) {
754
+ return {
755
+ node: node,
756
+ message: style_err,
757
+ };
758
+ }
759
+
760
+ // 检查长度
761
+ var len_err = this._checkNameLength(prop_name, rule.min, rule.max, rule_type);
762
+ if (len_err) {
763
+ return {
764
+ node: node,
765
+ message: len_err,
766
+ };
767
+ }
768
+
769
+ // 检查单词长度
770
+ var word_err = this._checkWordLength(prop_name, rule.single_word_len, rule_type);
771
+ if (word_err) {
772
+ return {
773
+ node: node,
774
+ message: word_err,
775
+ };
776
+ }
777
+
778
+ // 检查禁止词汇
779
+ var forbid_err = this._checkForbiddenWords(prop_name, rule_type);
780
+ if (forbid_err) {
781
+ return {
782
+ node: node,
783
+ message: forbid_err,
784
+ };
785
+ }
786
+
787
+ return null;
788
+ } catch (error) {
789
+ console.error('检测属性名时出错:', error);
790
+ return null;
791
+ }
792
+ };
793
+
794
+ /**
795
+ * 检查并推荐更合适的词汇
796
+ * @param {string} name 名称
797
+ * @param {string} name_type 名称类型
798
+ * @returns {string|null} 推荐信息或null
799
+ */
800
+ Detector.prototype._checkAndRecommend = function (name, name_type) {
801
+ try {
802
+ var rec_words = this.config.getRecommendedWords(name_type);
803
+ if (!rec_words || Object.keys(rec_words).length === 0) {
804
+ return null;
805
+ }
806
+
807
+ var name_lower = name.toLowerCase();
808
+
809
+ var name_type_desc = this.config.name_type_map[name_type] || '名称';
810
+ // 检查每个推荐词映射
811
+ for (var rec_word in rec_words) {
812
+ if (rec_words.hasOwnProperty(rec_word)) {
813
+ var original_words = rec_words[rec_word];
814
+
815
+ // 检查名称是否包含任何一个原词
816
+ for (var i = 0; i < original_words.length; i++) {
817
+ var original_word = original_words[i].toLowerCase();
818
+ if (name_lower.includes(original_word)) {
819
+ return name_type_desc + '建议使用\'' + rec_word + '\'替代\'' + original_words[i] + '\'以获得更短的命名';
820
+ }
821
+ }
822
+ }
823
+ }
824
+
825
+ return null;
826
+ } catch (error) {
827
+ console.error('检查并推荐更合适的词汇时出错:', error);
828
+ return null;
829
+ }
830
+ };
831
+
832
+ /**
833
+ * 检查值是否为基础值类型
834
+ * @param {object} val_node 值节点
835
+ * @returns {boolean} 是否为基础值
836
+ */
837
+ Detector.prototype._isBaseValue = function (val_node) {
838
+ try {
839
+ if (!val_node) {
840
+ return false;
841
+ }
842
+
843
+ // 检查是否为基础值类型
844
+ var is_base_value = false;
845
+
846
+ switch (val_node.type) {
847
+ case 'Literal': // 字面量:数字、字符串、布尔值
848
+ is_base_value = true;
849
+ break;
850
+ case 'ArrayExpression': // 数组字面量
851
+ is_base_value = true;
852
+ break;
853
+ case 'ObjectExpression': // 对象字面量
854
+ is_base_value = true;
855
+ break;
856
+ case 'UnaryExpression': // 一元表达式(如 -1, +100)
857
+ if (val_node.operator === '-' || val_node.operator === '+') {
858
+ is_base_value = true;
859
+ }
860
+ break;
861
+ default:
862
+ is_base_value = false;
863
+ }
864
+
865
+ return is_base_value;
866
+ } catch (error) {
867
+ console.error('检查值是否为基础值类型时出错:', error);
868
+ return false;
869
+ }
870
+ };
871
+
872
+ /**
873
+ * 检查值是否为复杂类型(方法、函数、实例等)
874
+ * @param {object} val_node 值节点
875
+ * @returns {boolean} 是否为复杂类型
876
+ */
877
+ Detector.prototype._isComplexType = function (val_node) {
878
+ try {
879
+ if (!val_node) {
880
+ return false;
881
+ }
882
+
883
+ // 检查是否为复杂类型
884
+ var is_complex_type = false;
885
+
886
+ switch (val_node.type) {
887
+ case 'FunctionExpression': // 函数表达式
888
+ case 'ArrowFunctionExpression': // 箭头函数
889
+ case 'NewExpression': // new 实例化
890
+ case 'CallExpression': // 函数调用
891
+ case 'MemberExpression': // 成员表达式
892
+ case 'Identifier': // 标识符(可能是变量或函数)
893
+ case 'ClassExpression': // 类表达式
894
+ case 'ThisExpression': // this表达式
895
+ case 'TemplateLiteral': // 模板字符串
896
+ is_complex_type = true;
897
+ break;
898
+ default:
899
+ is_complex_type = false;
900
+ }
901
+
902
+ return is_complex_type;
903
+ } catch (error) {
904
+ console.error('检查值是否为复杂类型时出错:', error);
905
+ return false;
906
+ }
907
+ };
908
+
909
+ /**
910
+ * 检查常量名是否符合规范
911
+ * @param {string} constant_name 常量名
912
+ * @returns {boolean} 是否符合规范
913
+ */
914
+ Detector.prototype._isConstantNameValid = function (constant_name) {
915
+ try {
916
+ var rule = this.config.getRule('constant-name');
917
+ if (!rule) {
918
+ return false;
919
+ }
920
+
921
+ // 检查命名风格
922
+ var style_err = this._validate_naming_style(constant_name, rule.styles, 'constant-name');
923
+ return !style_err;
924
+ } catch (error) {
925
+ console.error('检查常量名是否符合规范时出错:', error);
926
+ return false;
927
+ }
928
+ };
929
+
930
+ /**
931
+ * 检查是否为忽略词
932
+ * @param {string} name 名称
933
+ * @param {string} name_type 名称类型
934
+ * @returns {boolean} 是否为忽略词
935
+ */
936
+ Detector.prototype._isIgnoredWord = function (name, name_type) {
937
+ try {
938
+ var ignored_words = this.config.getIgnoredWords(name_type);
939
+ if (!ignored_words || !Array.isArray(ignored_words)) {
940
+ return false;
941
+ }
942
+
943
+ var name_lower = name.toLowerCase();
944
+ for (var i = 0; i < ignored_words.length; i++) {
945
+ if (ignored_words[i].toLowerCase() === name_lower) {
946
+ return true;
947
+ }
948
+ }
949
+
950
+ return false;
951
+ } catch (error) {
952
+ console.error('检查是否为忽略词时出错:', error);
953
+ return false;
954
+ }
955
+ };
956
+
957
+ /**
958
+ * 生成推荐命名
959
+ * @param {string} original_name 原始名称
960
+ * @param {string} long_word 过长的单词
961
+ * @param {string} name_type 名称类型
962
+ * @returns {string|null} 推荐命名或null
963
+ */
964
+ Detector.prototype._generateRecommendedName = function (original_name, long_word, name_type) {
965
+ try {
966
+ // 获取推荐词映射
967
+ var recommended_words = this.config.getRecommendedWords(name_type);
968
+ if (!recommended_words || Object.keys(recommended_words).length === 0) {
969
+ return null;
970
+ }
971
+
972
+ var long_word_lower = long_word.toLowerCase();
973
+
974
+ // 检查推荐词映射中是否有对应的缩写
975
+ for (var short_word in recommended_words) {
976
+ if (recommended_words.hasOwnProperty(short_word)) {
977
+ var original_words = recommended_words[short_word];
978
+
979
+ // 检查过长的单词是否在推荐词的原词列表中
980
+ for (var i = 0; i < original_words.length; i++) {
981
+ var original_word = original_words[i].toLowerCase();
982
+ if (long_word_lower === original_word) {
983
+ // 生成推荐命名:将原始名称中的长单词替换为推荐的缩写
984
+ var recommended_name = original_name.replace(long_word, short_word);
985
+ return recommended_name;
986
+ }
987
+ }
988
+ }
989
+ }
990
+
991
+ return null;
992
+ } catch (error) {
993
+ console.error('生成推荐命名时出错:', error);
994
+ return null;
995
+ }
996
+ };
997
+
998
+ module.exports = { Detector };