mm_eslint 1.4.5 → 1.4.7

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.
@@ -15,6 +15,7 @@ class Config {
15
15
  'class-instance': [],
16
16
  'function': [],
17
17
  'param': [],
18
+ 'object': [],
18
19
  'variable': [],
19
20
  'constant': []
20
21
  },
@@ -24,6 +25,7 @@ class Config {
24
25
  'class-instance': [],
25
26
  'function': [],
26
27
  'param': [],
28
+ 'object': [],
27
29
  'variable': [],
28
30
  'constant': []
29
31
  },
@@ -33,6 +35,7 @@ class Config {
33
35
  'class-instance': {},
34
36
  'function': {},
35
37
  'param': {},
38
+ 'object': {},
36
39
  'variable': {},
37
40
  'constant': {}
38
41
  }
@@ -65,7 +68,7 @@ Config.prototype.getRegex = function (style) {
65
68
  * @returns {Array} 禁止拼接词列表
66
69
  */
67
70
  Config.prototype.getForbiddenWords = function (name_type) {
68
- let type = name_type.replace('property-', '').replace('instance-', '').replace('private-', '').replace('internal-', '').replace('prototype-', '');
71
+ let type = this.getType(name_type);
69
72
  var forbidden = {
70
73
  'class': [
71
74
  'manager',
@@ -301,43 +304,27 @@ Config.prototype.getBaseRule = function (name_type) {
301
304
  single_word: true,
302
305
  single_word_len: 8
303
306
  },
304
- 'param-function': {
305
- name: '函数类型参数',
307
+ 'object': {
308
+ name: '对象名',
306
309
  min: 1,
307
310
  max: 20,
308
- styles: ['camelCase'],
309
- single_word: true,
310
- single_word_len: 8
311
- },
312
- 'param-class': {
313
- name: '类类型参数',
314
- min: 1,
315
- max: 20,
316
- styles: ['PascalCase'],
317
- single_word: true,
318
- single_word_len: 8
319
- },
320
- 'param-object': {
321
- name: '对象类型参数',
322
- min: 1,
323
- max: 20,
324
- styles: ['snake_case'],
311
+ styles: ['camelCase', 'snake_case'],
325
312
  single_word: true,
326
313
  single_word_len: 8
327
314
  },
328
- 'param-variable': {
329
- name: '变量类型参数',
315
+ 'variable': {
316
+ name: '变量名',
330
317
  min: 1,
331
318
  max: 20,
332
319
  styles: ['snake_case'],
333
320
  single_word: true,
334
321
  single_word_len: 8
335
322
  },
336
- 'variable': {
337
- name: '变量名',
323
+ 'property': {
324
+ name: '属性名',
338
325
  min: 1,
339
326
  max: 20,
340
- styles: ['snake_case'],
327
+ styles: ['snake_case', 'camelCase', 'PascalCase'],
341
328
  single_word: true,
342
329
  single_word_len: 8
343
330
  },
@@ -374,7 +361,7 @@ Config.prototype.getRule = function (name_type) {
374
361
  * @returns {object} 推荐词映射
375
362
  */
376
363
  Config.prototype.getRecommendWords = function (name_type) {
377
- let type = name_type.replace('property-', '').replace('instance-', '').replace('private-', '').replace('internal-', '').replace('prototype-', '');
364
+ let type = this.getType(name_type);
378
365
  var recommend = {
379
366
  'class': {
380
367
  'App': ['Application'],
@@ -487,17 +474,33 @@ Config.prototype.getRecommendWords = function (name_type) {
487
474
  return {};
488
475
  };
489
476
 
477
+ Config.prototype.getType = function (name_type) {
478
+ let type = name_type.replace('property-', '').replace('internal-', '').replace('private-', '').replace('internal-', '').replace('prototype-', '').replace('use-', '').replace('super-', '').replace('static-', '').replace('param-', '').replace('export-', '');
479
+ return type;
480
+ }
481
+
490
482
  /**
491
483
  * 获取忽略词列表
492
484
  * @param {string} name_type 名称类型
493
485
  * @returns {Array} 忽略词列表
494
486
  */
495
487
  Config.prototype.getIgnoreWords = function (name_type) {
496
- let type = name_type.replace('property-', '').replace('instance-', '').replace('private-', '').replace('internal-', '').replace('prototype-', '');
488
+ let type = this.getType(name_type);
497
489
  var ignore = {
498
490
  'class': [
499
491
  'exports', 'Middleware', 'Component', 'Controller', 'Repository', 'Interface', 'Transformer', 'Template'
500
492
  ],
493
+ 'class-instance': [
494
+ // JavaScript 内置全局对象(只保留不符合小驼峰规范的)
495
+ 'JSON', 'Math', 'RegExp', 'EvalError', 'RangeError', 'ReferenceError',
496
+ 'SyntaxError', 'TypeError', 'URIError', 'WeakMap', 'WeakSet', 'Promise',
497
+ 'Proxy', 'Reflect', 'Intl', 'ArrayBuffer', 'DataView', 'Float32Array', 'Float64Array',
498
+ 'Int8Array', 'Int16Array', 'Int32Array', 'Uint8Array', 'Uint16Array', 'Uint32Array',
499
+ 'Uint8ClampedArray', 'BigInt64Array', 'BigUint64Array', 'Atomics', 'SharedArrayBuffer',
500
+ 'URL', 'URLSearchParams', 'Headers', 'Request', 'Response', 'FormData', 'Blob', 'File',
501
+ 'FileReader', 'Image', 'Audio', 'Video', 'Canvas', 'WebSocket', 'EventSource',
502
+ 'XMLHttpRequest', 'Infinity', 'NaN', 'global'
503
+ ],
501
504
  'function': [
502
505
  'constructor', 'prototype', 'hasOwnProperty',
503
506
  'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString',
@@ -558,38 +561,62 @@ Config.prototype.getTypeNameMap = function () {
558
561
  var type_name_map = {
559
562
  'function': '函数',
560
563
  'variable': '变量',
561
- 'param': '参数',
564
+ 'object': '对象',
562
565
  'class-instance': '类实例',
563
566
  'class': '类',
564
567
  'constant': '常量',
568
+ 'super-class': '继承-类',
569
+ // 属性
570
+ 'property': '属性',
565
571
  'property-function': '属性—函数',
566
572
  'property-variable': '属性—变量',
573
+ 'property-object': '属性—对象',
567
574
  'property-class-instance': '属性—类实例',
568
575
  'property-class': '属性—类',
569
576
  'property-constant': '属性—常量',
577
+ // 静态属性
570
578
  'static-function': '静态属性—函数',
571
579
  'static-variable': '静态属性—变量',
580
+ 'static-object': '静态属性—对象',
572
581
  'static-class-instance': '静态属性—类实例',
573
582
  'static-class': '静态属性—类',
574
583
  'static-constant': '静态属性—常量',
575
- 'prototype-function': '原型函数',
576
- 'prototype-variable': '原型变量',
577
- 'prototype-class-instance': '原型类实例',
584
+ // 原型属性
585
+ 'prototype-class-instance': '原型属性—类实例',
586
+ 'prototype-function': '原型属性—函数',
587
+ 'prototype-variable': '原型属性—变量',
588
+ 'prototype-object': '原型属性—对象',
589
+ // 私有属性
578
590
  'private-function': '私有属性—函数',
579
591
  'private-variable': '私有属性—变量',
592
+ 'private-object': '私有属性—对象',
580
593
  'private-class-instance': '私有属性—类实例',
594
+ // 内部属性
581
595
  'internal-function': '内部属性—函数',
582
596
  'internal-variable': '内部属性—变量',
597
+ 'internal-object': '内部属性—对象',
583
598
  'internal-class-instance': '内部属性—类实例',
599
+ // 引用
584
600
  'use-variable': '引用-变量',
585
601
  'use-function': '引用-函数',
602
+ 'use-object': '引用-对象',
586
603
  'use-class': '引用-类',
587
604
  'use-constant': '引用-常量',
588
605
  'use-class-instance': '引用-类实例',
606
+ // 参数
607
+ 'param': '参数',
589
608
  'param-class': '参数—类',
590
609
  'param-class-instance': '参数—类实例',
591
610
  'param-variable': '参数—变量',
592
- 'param-function': '参数—函数'
611
+ 'param-object': '参数—对象',
612
+ 'param-function': '参数—函数',
613
+ // 导出
614
+ 'export-class': '导出-类',
615
+ 'export-class-instance': '导出-类实例',
616
+ 'export-variable': '导出-变量',
617
+ 'export-object': '导出-对象',
618
+ 'export-function': '导出-函数',
619
+ 'export-constant': '导出-常量'
593
620
  };
594
621
  return type_name_map;
595
622
  }
@@ -0,0 +1,246 @@
1
+ const { Name } = require('./name.js');
2
+
3
+ /**
4
+ * 类实例名检测器类
5
+ * 负责检测类实例名是否符合命名规范
6
+ */
7
+ class ClassInstanceName extends Name {
8
+ constructor(context, config) {
9
+ super(context, config);
10
+ }
11
+ }
12
+
13
+ /**
14
+ * 变量声明节点检测函数
15
+ * @param {Object} node - 变量声明节点
16
+ * @returns {Object|undefined} - 检测结果对象或undefined
17
+ */
18
+ ClassInstanceName.prototype.VariableDeclaration = function (node) {
19
+ // 判断右边是否有 new 表达式
20
+ if (node.declarations[0].init && node.declarations[0].init.type === 'NewExpression') {
21
+ let name = node.declarations[0].id.name;
22
+ let original_type = 'class-instance';
23
+ let error = this.check(node.declarations[0].id, name, original_type);
24
+ this.report(node.declarations[0].id, error, original_type);
25
+ return error;
26
+ }
27
+
28
+ // 判断右边是否有正则表达式字面量(RegExp实例)
29
+ if (node.declarations[0].init && node.declarations[0].init.type === 'Literal' &&
30
+ node.declarations[0].init.regex) {
31
+ let name = node.declarations[0].id.name;
32
+ let original_type = 'class-instance';
33
+ let error = this.check(node.declarations[0].id, name, original_type);
34
+ this.report(node.declarations[0].id, error, original_type);
35
+ return error;
36
+ }
37
+
38
+ // 判断右边是否直接赋值类实例名
39
+ if (node.declarations[0].init && node.declarations[0].init.type === 'Identifier') {
40
+ // 根据右边值的类型决定左边变量的类型
41
+ let original_type = this._getOriginalType(node.declarations[0], 'VariableDeclaration');
42
+
43
+ // 如果右边是类实例,左边变量应该按照类实例的命名规范检测(小驼峰)
44
+ if (original_type === 'class-instance') {
45
+ let name = node.declarations[0].id.name;
46
+ let error = this.check(node.declarations[0].id, name, 'class-instance');
47
+ this.report(node.declarations[0].id, error, 'class-instance');
48
+ return error;
49
+ }
50
+ }
51
+ }
52
+
53
+ /**
54
+ * 属性节点检测函数
55
+ * @param {Object} node - 属性节点
56
+ * @returns {Object|undefined} - 检测结果对象或undefined
57
+ */
58
+ ClassInstanceName.prototype.Property = function (node) {
59
+ // 判断右边是否有 new 表达式
60
+ if (node.value.type === 'NewExpression') {
61
+ let name = node.key.name;
62
+ let original_type = 'property-class-instance';
63
+ let error = this.check(node, name, original_type);
64
+ this.report(node, error, original_type);
65
+ return error;
66
+ }
67
+
68
+ // 判断右边是否直接定义为类实例名
69
+ if (node.value.type === 'Identifier') {
70
+ // 根据右边值的类型决定左边属性的类型
71
+ let original_type = this._getOriginalType(node, 'Property');
72
+
73
+ // 如果右边是类实例,左边属性应该按照类实例的命名规范检测(小驼峰)
74
+ if (original_type === 'class-instance') {
75
+ let name = node.key.name;
76
+ let error = this.check(node, name, 'property-class-instance');
77
+ this.report(node, error, 'property-class-instance');
78
+ return error;
79
+ }
80
+ }
81
+ }
82
+
83
+ /**
84
+ * 类属性定义节点检测函数
85
+ * @param {Object} node - 类属性定义节点
86
+ * @returns {Object|undefined} - 检测结果对象或undefined
87
+ */
88
+ ClassInstanceName.prototype.PropertyDefinition = function (node) {
89
+ // 判断右边是否有 new 表达式
90
+ if (node.value && node.value.type === 'NewExpression') {
91
+ let name = node.key.name;
92
+ let original_type = 'property-class-instance';
93
+ if (node.static) {
94
+ original_type = 'static-class-instance';
95
+ }
96
+ else if (node.key.type === 'PrivateIdentifier') {
97
+ original_type = 'private-class-instance';
98
+ }
99
+ else if (name.startsWith('_')) {
100
+ original_type = 'internal-class-instance';
101
+ }
102
+ let error = this.check(node, name, original_type);
103
+ this.report(node, error, original_type);
104
+ return error;
105
+ }
106
+
107
+ // 判断右边是否直接定义为类实例名
108
+ if (node.value && node.value.type === 'Identifier') {
109
+ // 根据右边值的类型决定左边属性的类型
110
+ let original_type = this._getOriginalType(node, 'PropertyDefinition');
111
+
112
+ // 如果右边是类实例,左边属性应该按照类实例的命名规范检测(小驼峰)
113
+ if (original_type === 'class-instance') {
114
+ let name = node.key.name;
115
+ let original_type = 'property-class-instance';
116
+ if (node.static) {
117
+ original_type = 'static-class-instance';
118
+ }
119
+ else if (node.key.type === 'PrivateIdentifier') {
120
+ original_type = 'private-class-instance';
121
+ }
122
+ else if (name.startsWith('_')) {
123
+ original_type = 'internal-class-instance';
124
+ }
125
+ let error = this.check(node, name, original_type);
126
+ this.report(node, error, original_type);
127
+ return error;
128
+ }
129
+ }
130
+ }
131
+
132
+ /**
133
+ * 赋值表达式节点检测函数
134
+ * @param {Object} node - 赋值表达式节点
135
+ * @returns {Object|undefined} - 检测结果对象或undefined
136
+ */
137
+ ClassInstanceName.prototype.AssignmentExpression = function (node) {
138
+ // 检测 exports 或 module.exports 赋值:exports.classInstance = classInstance;
139
+ // 排除右边是对象字面量的情况,交由Property检测器处理
140
+ if (node.operator === '=' && node.left && node.left.type === 'MemberExpression' &&
141
+ node.right && node.right.type !== 'ObjectExpression') {
142
+ // 检查左边是否为 exports 或 module.exports
143
+ let left_object = node.left.object;
144
+ let is_exports = false;
145
+
146
+ if (left_object.type === 'Identifier' && left_object.name === 'exports') {
147
+ is_exports = true;
148
+ } else if (left_object.type === 'MemberExpression' &&
149
+ left_object.object.type === 'Identifier' &&
150
+ left_object.object.name === 'module' &&
151
+ left_object.property.type === 'Identifier' &&
152
+ left_object.property.name === 'exports') {
153
+ is_exports = true;
154
+ }
155
+
156
+ if (is_exports && node.right && node.right.type === 'Identifier') {
157
+ // 先判断右边是否为类实例
158
+ let original_type = this._getOriginalType(node, 'AssignmentExpression');
159
+
160
+ // 如果右边是类实例,才检测左边的属性名
161
+ if (original_type === 'class-instance') {
162
+ let left_property = node.left.property;
163
+ if (left_property && left_property.type === 'Identifier') {
164
+ let name = left_property.name;
165
+ let error = this.check(left_property, name, 'property-class-instance');
166
+ this.report(left_property, error, 'property-class-instance');
167
+ return error;
168
+ }
169
+ }
170
+ }
171
+ }
172
+ }
173
+
174
+ /**
175
+ * 默认导出节点检测函数
176
+ * @param {Object} node - 默认导出节点
177
+ * @returns {Object|undefined} - 检测结果对象或undefined
178
+ */
179
+ ClassInstanceName.prototype.ExportDefaultDeclaration = function (node) {
180
+ // 检测导出的类实例名
181
+ if (node.declaration && node.declaration.type === 'Identifier') {
182
+ let name = node.declaration.name;
183
+ let type = this._getOriginalType(node.declaration, 'ExportDefaultDeclaration');
184
+ if (type === 'class-instance') {
185
+ let original_type = 'export-class-instance';
186
+ let error = this.check(node.declaration, name, original_type);
187
+ this.report(node.declaration, error, original_type);
188
+ return error;
189
+ }
190
+ }
191
+ }
192
+
193
+ /**
194
+ * 命名导出节点检测函数
195
+ * @param {Object} node - 命名导出节点
196
+ * @returns {Object|undefined} - 检测结果对象或undefined
197
+ */
198
+ ClassInstanceName.prototype.ExportNamedDeclaration = function (node) {
199
+ // 检测导出的类实例声明(如 export const myInstance = new ClassName())
200
+ if (node.declaration && node.declaration.type === 'VariableDeclaration') {
201
+ for (let i = 0; i < node.declaration.declarations.length; i++) {
202
+ let declaration = node.declaration.declarations[i];
203
+ if (declaration.init && declaration.init.type === 'NewExpression') {
204
+ let name = declaration.id.name;
205
+ let error = this.check(node, name, 'export-class-instance');
206
+ this.report(node, error, 'export-class-instance');
207
+ return error;
208
+ }
209
+ }
210
+ }
211
+
212
+ // 检测命名导出的类实例引用
213
+ if (node.specifiers && node.specifiers.length > 0) {
214
+ for (let i = 0; i < node.specifiers.length; i++) {
215
+ let specifier = node.specifiers[i];
216
+
217
+ // 检测导出的标识符(避免重复检测)
218
+ // 优先检测 exported 属性,如果存在则使用它,否则使用 local 属性
219
+ let identifier_to_check = null;
220
+ let identifier_name = '';
221
+
222
+ if (specifier.exported && specifier.exported.type === 'Identifier') {
223
+ identifier_to_check = specifier.exported;
224
+ identifier_name = specifier.exported.name;
225
+ } else if (specifier.local && specifier.local.type === 'Identifier') {
226
+ identifier_to_check = specifier.local;
227
+ identifier_name = specifier.local.name;
228
+ }
229
+
230
+ // 只有当找到有效标识符时才进行检测
231
+ if (identifier_to_check) {
232
+ let original_type = this._getOriginalType(specifier, 'ExportSpecifier');
233
+
234
+ // 只有当导出的是类实例时才检测
235
+ if (original_type === 'class-instance') {
236
+ let error = this.check(identifier_to_check, identifier_name, 'export-class-instance');
237
+ this.report(identifier_to_check, error, 'export-class-instance');
238
+ }
239
+ }
240
+ }
241
+ }
242
+ }
243
+
244
+ module.exports = {
245
+ ClassInstanceName
246
+ };