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.
- package/README.md +26 -0
- package/README_EN.md +27 -1
- package/index.js +153 -297
- package/{config.js → lib/config.js} +59 -32
- package/lib/detector/class_instance_name.js +246 -0
- package/lib/detector/class_name.js +261 -0
- package/lib/detector/const_name.js +529 -0
- package/lib/detector/function_name.js +318 -0
- package/lib/detector/index.js +18 -0
- package/lib/detector/name.js +626 -0
- package/lib/detector/object_name.js +245 -0
- package/lib/detector/param_name.js +247 -0
- package/lib/detector/variable_name.js +286 -0
- package/lib/fix/class_fix.js +83 -0
- package/lib/fix/export_fix.js +169 -0
- package/lib/fix/function_fix.js +85 -0
- package/lib/fix/index.js +21 -0
- package/lib/fix/method_fix.js +82 -0
- package/lib/fix/param_fix.js +63 -0
- package/lib/fix/property_fix.js +93 -0
- package/lib/fix/variable_fix.js +134 -0
- package/lib/fix.js +160 -0
- package/{util.js → lib/util.js} +8 -0
- package/{validator.js → lib/validator.js} +3 -3
- package/package.json +10 -13
- package/detector.js +0 -1291
- package/eslint.config.js +0 -25
- package/fix.js +0 -441
- package/handler.js +0 -993
- /package/{corrector.js → lib/corrector.js} +0 -0
- /package/{tip.js → lib/tip.js} +0 -0
|
@@ -0,0 +1,626 @@
|
|
|
1
|
+
const { Config } = require('../config.js');
|
|
2
|
+
const { Validator } = require('../validator.js');
|
|
3
|
+
const { Corrector } = require('../corrector.js');
|
|
4
|
+
const { Tip } = require('../tip.js');
|
|
5
|
+
const { Fix } = require('../fix.js');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 函数名检测器类
|
|
9
|
+
* 负责检测函数名是否符合命名规范
|
|
10
|
+
*/
|
|
11
|
+
class Name {
|
|
12
|
+
constructor(context, config) {
|
|
13
|
+
this.config = new Config();
|
|
14
|
+
Object.assign(this.config, config);
|
|
15
|
+
this.validator = new Validator(this.config);
|
|
16
|
+
this.corrector = new Corrector(this.config);
|
|
17
|
+
this.tip = new Tip(this.config);
|
|
18
|
+
this.fix = new Fix(this.config);
|
|
19
|
+
this.context = context;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* 检查函数名是否符合规范
|
|
25
|
+
* @param {Object} node - 节点对象
|
|
26
|
+
* @param {string} name - 节点名称
|
|
27
|
+
* @param {string} original_type - 源类型
|
|
28
|
+
* @returns {Object|undefined} - 检测结果对象或undefined
|
|
29
|
+
*/
|
|
30
|
+
Name.prototype.check = function (node, name, original_type) {
|
|
31
|
+
let error = this.validator.validate(name, original_type);
|
|
32
|
+
if (error) {
|
|
33
|
+
let suggestion = this.corrector.getSuggestion(error);
|
|
34
|
+
if (suggestion) {
|
|
35
|
+
error.suggestion = suggestion;
|
|
36
|
+
}
|
|
37
|
+
error.node = node;
|
|
38
|
+
error.message = this.tip.getFullMessage(error);
|
|
39
|
+
}
|
|
40
|
+
return error;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* 负责报告不符合命名规范的错误,并提供修复建议
|
|
45
|
+
* @param {Object} node - 节点对象
|
|
46
|
+
* @param {Object} error - 检测错误对象
|
|
47
|
+
* @param {string} type - 错误类型
|
|
48
|
+
*/
|
|
49
|
+
Name.prototype.report = function (node, error, type) {
|
|
50
|
+
if (!error) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// 设置错误类型信息
|
|
55
|
+
error.original_type = type;
|
|
56
|
+
|
|
57
|
+
// 如果有修复建议,创建修复函数
|
|
58
|
+
if (error.suggestion) {
|
|
59
|
+
error.fix_suggestion = error.suggestion;
|
|
60
|
+
|
|
61
|
+
// 使用新的模块化修复系统
|
|
62
|
+
error.fix = this.fix.createFixFunction(this.context, node, error);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// 设置错误位置信息
|
|
66
|
+
error.node = node;
|
|
67
|
+
|
|
68
|
+
// 对于变量声明,精确定位到标识符位置
|
|
69
|
+
if (node.type === 'VariableDeclaration' && node.declarations && node.declarations.length > 0) {
|
|
70
|
+
const declaration = node.declarations[0];
|
|
71
|
+
if (declaration.id && declaration.id.type === 'Identifier') {
|
|
72
|
+
// 使用标识符的位置作为错误位置
|
|
73
|
+
error.loc = declaration.id.loc;
|
|
74
|
+
}
|
|
75
|
+
} else if (node.type === 'Identifier') {
|
|
76
|
+
// 直接使用标识符的位置
|
|
77
|
+
error.loc = node.loc;
|
|
78
|
+
} else {
|
|
79
|
+
// 默认使用节点的位置
|
|
80
|
+
error.loc = node.loc;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
this.context.report(error);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* 根据赋值语句右边的标识符判断其原始类型
|
|
88
|
+
* @param {Object} node - 节点对象
|
|
89
|
+
* @param {string} node_type - 节点类型
|
|
90
|
+
* @returns {string} - 原始类型
|
|
91
|
+
*/
|
|
92
|
+
Name.prototype._getOriginalType = function (node, node_type) {
|
|
93
|
+
let right_identifier;
|
|
94
|
+
|
|
95
|
+
// 处理 VariableDeclaration 节点
|
|
96
|
+
if (node_type === 'VariableDeclaration' && node.init && node.init.type === 'Identifier') {
|
|
97
|
+
right_identifier = node.init;
|
|
98
|
+
}
|
|
99
|
+
// 处理 Property 节点
|
|
100
|
+
else if (node_type === 'Property' && node.value && node.value.type === 'Identifier') {
|
|
101
|
+
right_identifier = node.value;
|
|
102
|
+
}
|
|
103
|
+
// 处理 PropertyDefinition 节点(类属性)
|
|
104
|
+
else if (node_type === 'PropertyDefinition' && node.value && node.value.type === 'Identifier') {
|
|
105
|
+
right_identifier = node.value;
|
|
106
|
+
}
|
|
107
|
+
// 处理 AssignmentExpression 节点
|
|
108
|
+
else if (node_type === 'AssignmentExpression' && node.right && node.right.type === 'Identifier') {
|
|
109
|
+
right_identifier = node.right;
|
|
110
|
+
}
|
|
111
|
+
// 处理 ExportSpecifier 节点
|
|
112
|
+
else if (node_type === 'ExportSpecifier') {
|
|
113
|
+
// 优先检查 exported 属性(实际导出的标识符)
|
|
114
|
+
if (node.exported && node.exported.type === 'Identifier') {
|
|
115
|
+
right_identifier = node.exported;
|
|
116
|
+
}
|
|
117
|
+
// 如果没有 exported,检查 local 属性
|
|
118
|
+
else if (node.local && node.local.type === 'Identifier') {
|
|
119
|
+
right_identifier = node.local;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// 处理 ExportDefaultDeclaration 节点
|
|
123
|
+
else if (node_type === 'ExportDefaultDeclaration') {
|
|
124
|
+
// 处理默认导出(如 export default name)
|
|
125
|
+
right_identifier = node
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
return 'variable';
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (!right_identifier) {
|
|
132
|
+
return 'variable';
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
let right_name = right_identifier.name;
|
|
136
|
+
|
|
137
|
+
// 优化类型识别逻辑:根据标识符的实际定义准确判断类型
|
|
138
|
+
|
|
139
|
+
// 1. 首先检查是否为类(最精确的判断)
|
|
140
|
+
if (this._isClassInScope(right_name, node)) {
|
|
141
|
+
return 'class';
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// 2. 检查是否为类实例(需要精确判断)
|
|
145
|
+
if (this._isClassInstanceInScope(right_name, node)) {
|
|
146
|
+
return 'class-instance';
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// 3. 检查是否为函数(需要精确判断)
|
|
150
|
+
if (this._isFunctionInScope(right_name, node)) {
|
|
151
|
+
return 'function';
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// 4. 检查是否为常量
|
|
155
|
+
if (this._isConstantInScope(right_name, node)) {
|
|
156
|
+
return 'constant';
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// 5. 检查是否为对象
|
|
160
|
+
if (this._isObjectInScope(right_name, node)) {
|
|
161
|
+
return 'object';
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// 6. 检查是否为变量
|
|
165
|
+
if (this._isVariableInScope(right_name, node)) {
|
|
166
|
+
return 'variable';
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// 默认返回未知类型
|
|
170
|
+
return 'unknown';
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* 检查标识符是否在作用域内定义为类
|
|
175
|
+
* @param {string} name - 标识符名称
|
|
176
|
+
* @param {Object} node - 当前节点
|
|
177
|
+
* @returns {boolean} - 是否是类
|
|
178
|
+
*/
|
|
179
|
+
Name.prototype._isClassInScope = function (name, node) {
|
|
180
|
+
// 获取AST根节点
|
|
181
|
+
var program_node = this._getProgramNode(node);
|
|
182
|
+
if (!program_node) {
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// 遍历所有同级节点
|
|
187
|
+
for (var i = 0; i < program_node.body.length; i++) {
|
|
188
|
+
var sibling_node = program_node.body[i];
|
|
189
|
+
|
|
190
|
+
// 检查类声明
|
|
191
|
+
if (sibling_node.type === 'ClassDeclaration' && sibling_node.id && sibling_node.id.name === name) {
|
|
192
|
+
return true;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* 检查标识符是否在作用域内定义为函数
|
|
201
|
+
* @param {string} name - 标识符名称
|
|
202
|
+
* @param {Object} node - 当前节点
|
|
203
|
+
* @returns {boolean} - 是否是函数
|
|
204
|
+
*/
|
|
205
|
+
Name.prototype._isFunctionInScope = function (name, node) {
|
|
206
|
+
if (!name || !node) {
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// 获取AST根节点
|
|
211
|
+
let program_node = this._getProgramNode(node);
|
|
212
|
+
if (!program_node || !program_node.body) {
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// 遍历同级节点查找函数声明
|
|
217
|
+
for (let i = 0; i < program_node.body.length; i++) {
|
|
218
|
+
let sibling_node = program_node.body[i];
|
|
219
|
+
|
|
220
|
+
// 查找函数声明
|
|
221
|
+
if (sibling_node.type === 'FunctionDeclaration') {
|
|
222
|
+
if (sibling_node.id && sibling_node.id.type === 'Identifier' && sibling_node.id.name === name) {
|
|
223
|
+
return true;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// 查找变量声明中的函数表达式
|
|
228
|
+
if (sibling_node.type === 'VariableDeclaration') {
|
|
229
|
+
for (let j = 0; j < sibling_node.declarations.length; j++) {
|
|
230
|
+
let decl = sibling_node.declarations[j];
|
|
231
|
+
if (decl.id && decl.id.type === 'Identifier' && decl.id.name === name) {
|
|
232
|
+
// 检查是否为函数表达式
|
|
233
|
+
if (decl.init && (decl.init.type === 'FunctionExpression' || decl.init.type === 'ArrowFunctionExpression')) {
|
|
234
|
+
return true;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* 检查标识符是否在作用域内定义为对象
|
|
246
|
+
* @param {string} name - 标识符名称
|
|
247
|
+
* @param {Object} node - 当前节点
|
|
248
|
+
* @returns {boolean} - 是否是对象
|
|
249
|
+
*/
|
|
250
|
+
Name.prototype._isObjectInScope = function (name, node) {
|
|
251
|
+
if (!name || !node) {
|
|
252
|
+
return false;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// 获取AST根节点
|
|
256
|
+
let program_node = this._getProgramNode(node);
|
|
257
|
+
if (!program_node || !program_node.body) {
|
|
258
|
+
return false;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// 遍历同级节点查找对象声明
|
|
262
|
+
for (let i = 0; i < program_node.body.length; i++) {
|
|
263
|
+
let sibling_node = program_node.body[i];
|
|
264
|
+
|
|
265
|
+
// 查找变量声明中的对象
|
|
266
|
+
if (sibling_node.type === 'VariableDeclaration') {
|
|
267
|
+
for (let j = 0; j < sibling_node.declarations.length; j++) {
|
|
268
|
+
let decl = sibling_node.declarations[j];
|
|
269
|
+
if (decl.id && decl.id.type === 'Identifier' && decl.id.name === name) {
|
|
270
|
+
// 检查是否为对象表达式
|
|
271
|
+
if (decl.init && decl.init.type === 'ObjectExpression') {
|
|
272
|
+
return true;
|
|
273
|
+
}
|
|
274
|
+
// 检查是否为数组表达式(也视为对象的一种)
|
|
275
|
+
if (decl.init && decl.init.type === 'ArrayExpression') {
|
|
276
|
+
return true;
|
|
277
|
+
}
|
|
278
|
+
// 检查是否为函数调用返回的对象
|
|
279
|
+
if (decl.init && decl.init.type === 'CallExpression') {
|
|
280
|
+
return this._isFunctionReturningObject(decl.init);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// 查找赋值表达式中的对象
|
|
287
|
+
if (sibling_node.type === 'ExpressionStatement' && sibling_node.expression && sibling_node.expression.type === 'AssignmentExpression') {
|
|
288
|
+
let expr = sibling_node.expression;
|
|
289
|
+
if (expr.left && expr.left.type === 'Identifier' && expr.left.name === name) {
|
|
290
|
+
// 检查右边是否为对象表达式
|
|
291
|
+
if (expr.right && expr.right.type === 'ObjectExpression') {
|
|
292
|
+
return true;
|
|
293
|
+
}
|
|
294
|
+
// 检查右边是否为数组表达式
|
|
295
|
+
if (expr.right && expr.right.type === 'ArrayExpression') {
|
|
296
|
+
return true;
|
|
297
|
+
}
|
|
298
|
+
// 检查右边是否为函数调用返回的对象
|
|
299
|
+
if (expr.right && expr.right.type === 'CallExpression') {
|
|
300
|
+
return this._isFunctionReturningObject(expr.right);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
return false;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* 检查标识符是否在作用域内定义为常量
|
|
311
|
+
* @param {string} name - 标识符名称
|
|
312
|
+
* @param {Object} node - 当前节点
|
|
313
|
+
* @returns {boolean} - 是否是常量
|
|
314
|
+
*/
|
|
315
|
+
Name.prototype._isConstantInScope = function (name, node) {
|
|
316
|
+
if (!name || !node) {
|
|
317
|
+
return false;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// 获取AST根节点
|
|
321
|
+
let program_node = this._getProgramNode(node);
|
|
322
|
+
if (!program_node || !program_node.body) {
|
|
323
|
+
return false;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// 遍历同级节点查找常量声明
|
|
327
|
+
for (let i = 0; i < program_node.body.length; i++) {
|
|
328
|
+
let sibling_node = program_node.body[i];
|
|
329
|
+
|
|
330
|
+
// 查找常量声明(const)
|
|
331
|
+
if (sibling_node.type === 'VariableDeclaration' && sibling_node.kind === 'const') {
|
|
332
|
+
for (let j = 0; j < sibling_node.declarations.length; j++) {
|
|
333
|
+
let decl = sibling_node.declarations[j];
|
|
334
|
+
if (decl.id && decl.id.type === 'Identifier' && decl.id.name === name) {
|
|
335
|
+
return true;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
return false;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* 检查标识符是否在作用域内定义为变量
|
|
346
|
+
* @param {string} name - 标识符名称
|
|
347
|
+
* @param {Object} node - 当前节点
|
|
348
|
+
* @returns {boolean} - 是否是变量
|
|
349
|
+
*/
|
|
350
|
+
Name.prototype._isVariableInScope = function (name, node) {
|
|
351
|
+
if (!name || !node) {
|
|
352
|
+
return false;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// 获取AST根节点
|
|
356
|
+
let program_node = this._getProgramNode(node);
|
|
357
|
+
if (!program_node || !program_node.body) {
|
|
358
|
+
return false;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// 遍历同级节点查找变量声明
|
|
362
|
+
for (let i = 0; i < program_node.body.length; i++) {
|
|
363
|
+
let sibling_node = program_node.body[i];
|
|
364
|
+
|
|
365
|
+
// 查找变量声明(let 和 var)
|
|
366
|
+
if (sibling_node.type === 'VariableDeclaration' && (sibling_node.kind === 'let' || sibling_node.kind === 'var')) {
|
|
367
|
+
for (let j = 0; j < sibling_node.declarations.length; j++) {
|
|
368
|
+
let decl = sibling_node.declarations[j];
|
|
369
|
+
if (decl.id && decl.id.type === 'Identifier' && decl.id.name === name) {
|
|
370
|
+
return true;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
return false;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* 检查标识符是否在作用域内定义为类实例
|
|
381
|
+
* @param {string} name - 标识符名称
|
|
382
|
+
* @param {Object} node - 当前节点
|
|
383
|
+
* @returns {boolean} - 是否是类实例
|
|
384
|
+
*/
|
|
385
|
+
Name.prototype._isClassInstanceInScope = function (name, node) {
|
|
386
|
+
if (!name || !node) {
|
|
387
|
+
return false;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// 获取AST根节点
|
|
391
|
+
let program_node = this._getProgramNode(node);
|
|
392
|
+
if (!program_node || !program_node.body) {
|
|
393
|
+
return false;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// 遍历同级节点查找类实例声明
|
|
397
|
+
for (let i = 0; i < program_node.body.length; i++) {
|
|
398
|
+
let sibling_node = program_node.body[i];
|
|
399
|
+
|
|
400
|
+
// 查找变量声明(let 和 var)
|
|
401
|
+
if (sibling_node.type === 'VariableDeclaration' && (sibling_node.kind === 'let' || sibling_node.kind === 'var' || sibling_node.kind === 'const')) {
|
|
402
|
+
for (let j = 0; j < sibling_node.declarations.length; j++) {
|
|
403
|
+
let decl = sibling_node.declarations[j];
|
|
404
|
+
|
|
405
|
+
// 检查右边是否为 new 表达式
|
|
406
|
+
if (decl.id && decl.id.type === 'Identifier' && decl.id.name === name && decl.init && decl.init.type === 'NewExpression') {
|
|
407
|
+
return true;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
// 查找属性声明
|
|
413
|
+
if (sibling_node.type === 'ExpressionStatement' && sibling_node.expression && sibling_node.expression.type === 'AssignmentExpression') {
|
|
414
|
+
let expr = sibling_node.expression;
|
|
415
|
+
// 检查左边是否为标识符,右边是否为 new 表达式
|
|
416
|
+
if (expr.left && expr.left.type === 'Identifier' && expr.left.name === name && expr.right && expr.right.type === 'NewExpression') {
|
|
417
|
+
return true;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
return false;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* 检查函数调用是否返回对象
|
|
427
|
+
* @param {Object} call_expr - 函数调用表达式节点
|
|
428
|
+
* @returns {boolean} - 是否返回对象
|
|
429
|
+
*/
|
|
430
|
+
Name.prototype._isFunctionReturningObject = function (call_expr) {
|
|
431
|
+
if (!call_expr || call_expr.type !== 'CallExpression') {
|
|
432
|
+
return false;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// 获取被调用的函数标识符
|
|
436
|
+
let callee = call_expr.callee;
|
|
437
|
+
if (!callee || callee.type !== 'Identifier') {
|
|
438
|
+
return false;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
let func_name = callee.name;
|
|
442
|
+
|
|
443
|
+
// 获取AST根节点
|
|
444
|
+
let program_node = this._getProgramNode(call_expr);
|
|
445
|
+
if (!program_node || !program_node.body) {
|
|
446
|
+
return false;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
// 遍历查找函数定义
|
|
450
|
+
for (let i = 0; i < program_node.body.length; i++) {
|
|
451
|
+
let sibling_node = program_node.body[i];
|
|
452
|
+
|
|
453
|
+
// 查找函数声明
|
|
454
|
+
if (sibling_node.type === 'FunctionDeclaration' && sibling_node.id && sibling_node.id.name === func_name) {
|
|
455
|
+
// 检查函数体是否返回对象
|
|
456
|
+
return this._doesFunctionReturnObject(sibling_node);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// 查找变量声明中的函数表达式
|
|
460
|
+
if (sibling_node.type === 'VariableDeclaration') {
|
|
461
|
+
for (let j = 0; j < sibling_node.declarations.length; j++) {
|
|
462
|
+
let decl = sibling_node.declarations[j];
|
|
463
|
+
if (decl.id && decl.id.type === 'Identifier' && decl.id.name === func_name && decl.init) {
|
|
464
|
+
// 检查是否为函数表达式
|
|
465
|
+
if (decl.init.type === 'FunctionExpression' || decl.init.type === 'ArrowFunctionExpression') {
|
|
466
|
+
return this._doesFunctionReturnObject(decl.init);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
return false;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* 检查函数是否返回对象
|
|
478
|
+
* @param {Object} func_node - 函数节点
|
|
479
|
+
* @returns {boolean} - 是否返回对象
|
|
480
|
+
*/
|
|
481
|
+
Name.prototype._doesFunctionReturnObject = function (func_node) {
|
|
482
|
+
if (!func_node || !func_node.body) {
|
|
483
|
+
return false;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
// 检查函数体中的返回语句
|
|
487
|
+
let body = func_node.body;
|
|
488
|
+
|
|
489
|
+
// 如果是块语句,遍历其中的语句
|
|
490
|
+
if (body.type === 'BlockStatement' && body.body) {
|
|
491
|
+
for (let i = 0; i < body.body.length; i++) {
|
|
492
|
+
let stmt = body.body[i];
|
|
493
|
+
if (stmt.type === 'ReturnStatement' && stmt.argument) {
|
|
494
|
+
// 检查返回值是否为对象表达式
|
|
495
|
+
if (stmt.argument.type === 'ObjectExpression') {
|
|
496
|
+
return true;
|
|
497
|
+
}
|
|
498
|
+
// 检查返回值是否为数组表达式
|
|
499
|
+
if (stmt.argument.type === 'ArrayExpression') {
|
|
500
|
+
return true;
|
|
501
|
+
}
|
|
502
|
+
// 检查返回值是否为函数调用(可能返回对象)
|
|
503
|
+
if (stmt.argument.type === 'CallExpression') {
|
|
504
|
+
return true; // 保守估计,假设函数调用可能返回对象
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// 对于箭头函数,如果是表达式体,直接检查返回值
|
|
511
|
+
if (func_node.type === 'ArrowFunctionExpression' && body.type !== 'BlockStatement') {
|
|
512
|
+
// 检查表达式体是否为对象表达式
|
|
513
|
+
if (body.type === 'ObjectExpression') {
|
|
514
|
+
return true;
|
|
515
|
+
}
|
|
516
|
+
// 检查表达式体是否为数组表达式
|
|
517
|
+
if (body.type === 'ArrayExpression') {
|
|
518
|
+
return true;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
return false;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
/**
|
|
526
|
+
* 获取AST根节点
|
|
527
|
+
* @param {Object} node - 当前节点
|
|
528
|
+
* @returns {Object} - 根节点
|
|
529
|
+
*/
|
|
530
|
+
Name.prototype._getProgramNode = function (node) {
|
|
531
|
+
while (node && node.parent) {
|
|
532
|
+
node = node.parent;
|
|
533
|
+
}
|
|
534
|
+
return node;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
/**
|
|
538
|
+
* 判断属性是否在常量对象中
|
|
539
|
+
* @param {Object} node - 属性节点
|
|
540
|
+
* @returns {boolean} 是否在常量对象中
|
|
541
|
+
*/
|
|
542
|
+
Name.prototype._isInConstantObject = function (node) {
|
|
543
|
+
// 向上查找父节点,判断是否在常量声明中
|
|
544
|
+
let current_node = node;
|
|
545
|
+
while (current_node.parent) {
|
|
546
|
+
// 排除函数体内的对象字面量
|
|
547
|
+
if (this._isInFunctionBody(current_node)) {
|
|
548
|
+
return false;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
// 检查是否为常量声明(const)中的对象字面量
|
|
552
|
+
if (current_node.parent.type === 'VariableDeclarator' &&
|
|
553
|
+
current_node.parent.parent &&
|
|
554
|
+
current_node.parent.parent.type === 'VariableDeclaration' &&
|
|
555
|
+
current_node.parent.parent.kind === 'const') {
|
|
556
|
+
return true;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
// 检查是否为 Object.freeze() 调用中的对象字面量
|
|
560
|
+
if (current_node.parent.type === 'CallExpression' &&
|
|
561
|
+
current_node.parent.callee &&
|
|
562
|
+
current_node.parent.callee.type === 'MemberExpression' &&
|
|
563
|
+
current_node.parent.callee.object &&
|
|
564
|
+
current_node.parent.callee.object.name === 'Object' &&
|
|
565
|
+
current_node.parent.callee.property &&
|
|
566
|
+
current_node.parent.callee.property.name === 'freeze') {
|
|
567
|
+
return true;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
// 检查是否为 Object.seal() 调用中的对象字面量
|
|
571
|
+
if (current_node.parent.type === 'CallExpression' &&
|
|
572
|
+
current_node.parent.callee &&
|
|
573
|
+
current_node.parent.callee.type === 'MemberExpression' &&
|
|
574
|
+
current_node.parent.callee.object &&
|
|
575
|
+
current_node.parent.callee.object.name === 'Object' &&
|
|
576
|
+
current_node.parent.callee.property &&
|
|
577
|
+
current_node.parent.callee.property.name === 'seal') {
|
|
578
|
+
return true;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
// 检查是否为 Object.preventExtensions() 调用中的对象字面量
|
|
582
|
+
if (current_node.parent.type === 'CallExpression' &&
|
|
583
|
+
current_node.parent.callee &&
|
|
584
|
+
current_node.parent.callee.type === 'MemberExpression' &&
|
|
585
|
+
current_node.parent.callee.object &&
|
|
586
|
+
current_node.parent.callee.object.name === 'Object' &&
|
|
587
|
+
current_node.parent.callee.property &&
|
|
588
|
+
current_node.parent.callee.property.name === 'preventExtensions') {
|
|
589
|
+
return true;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
current_node = current_node.parent;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
return false;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
/**
|
|
599
|
+
* 判断节点是否在函数体内
|
|
600
|
+
* @param {Object} node - 节点
|
|
601
|
+
* @returns {boolean} 是否在函数体内
|
|
602
|
+
*/
|
|
603
|
+
Name.prototype._isInFunctionBody = function (node) {
|
|
604
|
+
let current_node = node;
|
|
605
|
+
while (current_node.parent) {
|
|
606
|
+
// 检查是否在函数声明或函数表达式中
|
|
607
|
+
if (current_node.parent.type === 'FunctionDeclaration' ||
|
|
608
|
+
current_node.parent.type === 'FunctionExpression' ||
|
|
609
|
+
current_node.parent.type === 'ArrowFunctionExpression') {
|
|
610
|
+
return true;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
// 检查是否在箭头函数的表达式体内(没有大括号的情况)
|
|
614
|
+
if (current_node.parent.type === 'ArrowFunctionExpression') {
|
|
615
|
+
return true;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
current_node = current_node.parent;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
return false;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
module.exports = {
|
|
625
|
+
Name
|
|
626
|
+
};
|