mm_eslint 1.0.7 → 1.0.9
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 +91 -0
- package/README_EN.md +91 -0
- package/index.js +515 -47
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
- ✅ **单词长度限制** - 每个单词限制在最大8字符
|
|
18
18
|
- ✅ **禁止废话词** - 避免使用Manager、Handler等冗余词汇
|
|
19
19
|
- ✅ **JSDoc支持** - 集成JSDoc文档要求
|
|
20
|
+
- ✅ **命名推荐功能** - 推荐更短的替代名称,同时保持语义不变
|
|
20
21
|
|
|
21
22
|
## 安装
|
|
22
23
|
|
|
@@ -268,8 +269,98 @@ const customConfig = {
|
|
|
268
269
|
};
|
|
269
270
|
|
|
270
271
|
const detector = new NamingDetector(customConfig);
|
|
272
|
+
|
|
273
|
+
## 命名推荐功能
|
|
274
|
+
|
|
275
|
+
插件包含智能命名推荐系统,建议使用更短的替代名称,同时保持语义不变。
|
|
276
|
+
|
|
277
|
+
### 核心原则
|
|
278
|
+
|
|
279
|
+
核心原则是**"缩短命名而不改变语义"**。推荐系统:
|
|
280
|
+
- 推荐更短的单词,同时保持相同含义
|
|
281
|
+
- 避免会改变功能的概念性变化
|
|
282
|
+
- 确保推荐词始终比原词短
|
|
283
|
+
- 保留编程特定术语和概念差异
|
|
284
|
+
|
|
285
|
+
### 配置
|
|
286
|
+
|
|
287
|
+
在ESLint配置中启用推荐功能:
|
|
288
|
+
|
|
289
|
+
```javascript
|
|
290
|
+
// eslint.config.js
|
|
291
|
+
const namingConventionPlugin = require("mm_eslint");
|
|
292
|
+
|
|
293
|
+
module.exports = [
|
|
294
|
+
{
|
|
295
|
+
files: ["**/*.js"],
|
|
296
|
+
plugins: {
|
|
297
|
+
"naming-convention": namingConventionPlugin,
|
|
298
|
+
},
|
|
299
|
+
rules: {
|
|
300
|
+
"naming-convention/class-name": "error",
|
|
301
|
+
"naming-convention/function-name": ["error", { recommen: true }], // 启用推荐功能
|
|
302
|
+
// ... 其他规则
|
|
303
|
+
},
|
|
304
|
+
},
|
|
305
|
+
];
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### 可用推荐
|
|
309
|
+
|
|
310
|
+
插件为常见编程操作提供推荐:
|
|
311
|
+
|
|
312
|
+
| 原词 | 推荐词 | 描述 |
|
|
313
|
+
|------|--------|------|
|
|
314
|
+
| `calculate` | `calc` | 数学运算 |
|
|
315
|
+
| `generate` | `gen` | 数据生成 |
|
|
316
|
+
| `initialize` | `init` | 初始化操作 |
|
|
317
|
+
| `execute` | `exec` | 命令执行 |
|
|
318
|
+
| `process` | `run` | 数据处理 |
|
|
319
|
+
| `retrieve` | `load` | 数据加载 |
|
|
320
|
+
| `persist` | `save` | 数据存储 |
|
|
321
|
+
| `compare` | `cmp` | 比较操作 |
|
|
322
|
+
| `duplicate` | `copy` | 数据复制 |
|
|
323
|
+
| `transfer` | `move` | 数据移动 |
|
|
324
|
+
| `convert` | `to` | 类型转换 |
|
|
325
|
+
| `verify` | `check` | 验证检查 |
|
|
326
|
+
| `construct` | `create` | 对象创建 |
|
|
327
|
+
| `handle` | `run` | 事件处理 |
|
|
328
|
+
|
|
329
|
+
### 示例
|
|
330
|
+
|
|
331
|
+
```javascript
|
|
332
|
+
// ❌ 原词(较长名称)
|
|
333
|
+
function calculateTotal() {}
|
|
334
|
+
function generateUserData() {}
|
|
335
|
+
function initializeSystem() {}
|
|
336
|
+
function executeCommand() {}
|
|
337
|
+
function processData() {}
|
|
338
|
+
|
|
339
|
+
// ✅ 推荐词(较短名称)
|
|
340
|
+
function calcTotal() {}
|
|
341
|
+
function genUserData() {}
|
|
342
|
+
function initSystem() {}
|
|
343
|
+
function execCommand() {}
|
|
344
|
+
function runData() {}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### 带推荐的错误消息
|
|
348
|
+
|
|
349
|
+
启用推荐功能后,ESLint将建议替代名称:
|
|
350
|
+
|
|
351
|
+
```bash
|
|
352
|
+
# ESLint输出示例
|
|
353
|
+
function calculateTotal() {}
|
|
354
|
+
# ^ 建议使用'calc'替代'calculate'以获得更短的命名
|
|
271
355
|
```
|
|
272
356
|
|
|
357
|
+
### 优势
|
|
358
|
+
|
|
359
|
+
1. **提高可读性**:更短的名称更容易阅读和理解
|
|
360
|
+
2. **一致的代码库**:项目中的标准化命名
|
|
361
|
+
3. **语义保持**:在减少冗长的同时保持含义
|
|
362
|
+
4. **编程最佳实践**:遵循简洁命名的行业标准
|
|
363
|
+
|
|
273
364
|
## 开发
|
|
274
365
|
|
|
275
366
|
### 项目结构
|
package/README_EN.md
CHANGED
|
@@ -17,6 +17,7 @@ An ESLint plugin based on personal naming conventions, supporting naming convent
|
|
|
17
17
|
- ✅ **Word Length Limit** - Each word limited to maximum 8 characters
|
|
18
18
|
- ✅ **Forbidden Words** - Avoids redundant words like Manager, Handler, etc.
|
|
19
19
|
- ✅ **JSDoc Support** - Integrated JSDoc documentation requirements
|
|
20
|
+
- ✅ **Naming Recommendations** - Recommends shorter alternative names while preserving semantic meaning
|
|
20
21
|
|
|
21
22
|
## Installation
|
|
22
23
|
|
|
@@ -268,8 +269,98 @@ const customConfig = {
|
|
|
268
269
|
};
|
|
269
270
|
|
|
270
271
|
const detector = new NamingDetector(customConfig);
|
|
272
|
+
|
|
273
|
+
## Naming Recommendation Feature
|
|
274
|
+
|
|
275
|
+
The plugin includes an intelligent naming recommendation system that suggests shorter alternative names while preserving semantic meaning.
|
|
276
|
+
|
|
277
|
+
### Principle
|
|
278
|
+
|
|
279
|
+
The core principle is **"shorten names without changing semantics"**. The recommendation system:
|
|
280
|
+
- Recommends shorter words that maintain the same meaning
|
|
281
|
+
- Avoids conceptual changes that would alter functionality
|
|
282
|
+
- Ensures recommended words are always shorter than the original
|
|
283
|
+
- Preserves programming-specific terminology and conceptual differences
|
|
284
|
+
|
|
285
|
+
### Configuration
|
|
286
|
+
|
|
287
|
+
Enable the recommendation feature in your ESLint configuration:
|
|
288
|
+
|
|
289
|
+
```javascript
|
|
290
|
+
// eslint.config.js
|
|
291
|
+
const namingConventionPlugin = require("mm-eslint-plugin");
|
|
292
|
+
|
|
293
|
+
module.exports = [
|
|
294
|
+
{
|
|
295
|
+
files: ["**/*.js"],
|
|
296
|
+
plugins: {
|
|
297
|
+
"naming-convention": namingConventionPlugin,
|
|
298
|
+
},
|
|
299
|
+
rules: {
|
|
300
|
+
"naming-convention/class-name": "error",
|
|
301
|
+
"naming-convention/function-name": ["error", { recommen: true }], // Enable recommendations
|
|
302
|
+
// ... other rules
|
|
303
|
+
},
|
|
304
|
+
},
|
|
305
|
+
];
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### Available Recommendations
|
|
309
|
+
|
|
310
|
+
The plugin provides recommendations for common programming operations:
|
|
311
|
+
|
|
312
|
+
| Original Word | Recommended Word | Description |
|
|
313
|
+
|---------------|------------------|-------------|
|
|
314
|
+
| `calculate` | `calc` | Mathematical operations |
|
|
315
|
+
| `generate` | `gen` | Data generation |
|
|
316
|
+
| `initialize` | `init` | Initialization operations |
|
|
317
|
+
| `execute` | `exec` | Command execution |
|
|
318
|
+
| `process` | `run` | Data processing |
|
|
319
|
+
| `retrieve` | `load` | Data loading |
|
|
320
|
+
| `persist` | `save` | Data storage |
|
|
321
|
+
| `compare` | `cmp` | Comparison operations |
|
|
322
|
+
| `duplicate` | `copy` | Data copying |
|
|
323
|
+
| `transfer` | `move` | Data movement |
|
|
324
|
+
| `convert` | `to` | Type conversion |
|
|
325
|
+
| `verify` | `check` | Validation checks |
|
|
326
|
+
| `construct` | `create` | Object creation |
|
|
327
|
+
| `handle` | `run` | Event handling |
|
|
328
|
+
|
|
329
|
+
### Examples
|
|
330
|
+
|
|
331
|
+
```javascript
|
|
332
|
+
// ❌ Original (longer names)
|
|
333
|
+
function calculateTotal() {}
|
|
334
|
+
function generateUserData() {}
|
|
335
|
+
function initializeSystem() {}
|
|
336
|
+
function executeCommand() {}
|
|
337
|
+
function processData() {}
|
|
338
|
+
|
|
339
|
+
// ✅ Recommended (shorter names)
|
|
340
|
+
function calcTotal() {}
|
|
341
|
+
function genUserData() {}
|
|
342
|
+
function initSystem() {}
|
|
343
|
+
function execCommand() {}
|
|
344
|
+
function runData() {}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### Error Messages with Recommendations
|
|
348
|
+
|
|
349
|
+
When the recommendation feature is enabled, ESLint will suggest alternative names:
|
|
350
|
+
|
|
351
|
+
```bash
|
|
352
|
+
# ESLint output example
|
|
353
|
+
function calculateTotal() {}
|
|
354
|
+
# ^ Recommend using 'calc' instead of 'calculate' for shorter naming
|
|
271
355
|
```
|
|
272
356
|
|
|
357
|
+
### Benefits
|
|
358
|
+
|
|
359
|
+
1. **Improved Readability**: Shorter names are easier to read and understand
|
|
360
|
+
2. **Consistent Codebase**: Standardized naming across the project
|
|
361
|
+
3. **Semantic Preservation**: Meaning is maintained while reducing verbosity
|
|
362
|
+
4. **Programming Best Practices**: Follows industry standards for concise naming
|
|
363
|
+
|
|
273
364
|
## Development
|
|
274
365
|
|
|
275
366
|
### Project Structure
|
package/index.js
CHANGED
|
@@ -5,19 +5,239 @@
|
|
|
5
5
|
*/
|
|
6
6
|
class Detector {
|
|
7
7
|
static config = {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
8
|
+
// 推荐词功能开关
|
|
9
|
+
recommen: true,
|
|
10
|
+
// 推荐词,当命名时较长时推荐使用的词
|
|
11
|
+
recommen_words: {
|
|
12
|
+
// 函数推荐词
|
|
13
|
+
function: {
|
|
14
|
+
// === 动词类 ===
|
|
15
|
+
// 增加
|
|
16
|
+
add: {
|
|
17
|
+
words: ["push", "insert"]
|
|
18
|
+
},
|
|
19
|
+
// 删除
|
|
20
|
+
del: {
|
|
21
|
+
words: ["remove", "delete"]
|
|
22
|
+
},
|
|
23
|
+
// 查询
|
|
24
|
+
get: {
|
|
25
|
+
words: ["query"]
|
|
26
|
+
},
|
|
27
|
+
// 修改
|
|
28
|
+
set: {
|
|
29
|
+
words: ["setting"]
|
|
30
|
+
},
|
|
31
|
+
// 转换
|
|
32
|
+
to: {
|
|
33
|
+
words: ["convert", "transform"]
|
|
34
|
+
},
|
|
35
|
+
// 检查
|
|
36
|
+
check: {
|
|
37
|
+
words: ["verify", "validate", "confirm"]
|
|
38
|
+
},
|
|
39
|
+
// 创建
|
|
40
|
+
create: {
|
|
41
|
+
words: ["construct"]
|
|
42
|
+
},
|
|
43
|
+
// 生成
|
|
44
|
+
gen: {
|
|
45
|
+
words: ["generate"]
|
|
46
|
+
},
|
|
47
|
+
// 初始化
|
|
48
|
+
init: {
|
|
49
|
+
words: ["initialize"]
|
|
50
|
+
},
|
|
51
|
+
// 处理
|
|
52
|
+
run: {
|
|
53
|
+
words: ["process", "handle"]
|
|
54
|
+
},
|
|
55
|
+
// 执行
|
|
56
|
+
exec: {
|
|
57
|
+
words: ["execute"]
|
|
58
|
+
},
|
|
59
|
+
// 计算
|
|
60
|
+
calc: {
|
|
61
|
+
words: ["calculate", "compute"]
|
|
62
|
+
},
|
|
63
|
+
// 加载
|
|
64
|
+
load: {
|
|
65
|
+
words: ["fetch", "retrieve"]
|
|
66
|
+
},
|
|
67
|
+
// 保存
|
|
68
|
+
save: {
|
|
69
|
+
words: ["store", "persist"]
|
|
70
|
+
},
|
|
71
|
+
// 比较
|
|
72
|
+
cmp: {
|
|
73
|
+
words: ["compare", "diff"]
|
|
74
|
+
},
|
|
75
|
+
// 排序
|
|
76
|
+
sort: {
|
|
77
|
+
words: ["order", "arrange"]
|
|
78
|
+
},
|
|
79
|
+
// 查找
|
|
80
|
+
find: {
|
|
81
|
+
words: ["search", "locate"]
|
|
82
|
+
},
|
|
83
|
+
// 删除
|
|
84
|
+
del: {
|
|
85
|
+
words: ["remove", "delete"]
|
|
86
|
+
},
|
|
87
|
+
// 解析
|
|
88
|
+
parse: {
|
|
89
|
+
words: ["analyze"]
|
|
90
|
+
},
|
|
91
|
+
// 复制
|
|
92
|
+
copy: {
|
|
93
|
+
words: ["duplicate", "clone"]
|
|
94
|
+
},
|
|
95
|
+
// 移动
|
|
96
|
+
move: {
|
|
97
|
+
words: ["transfer", "relocate"]
|
|
98
|
+
},
|
|
99
|
+
// 压缩
|
|
100
|
+
zip: {
|
|
101
|
+
words: ["compress"]
|
|
102
|
+
},
|
|
103
|
+
// 解压
|
|
104
|
+
unzip: {
|
|
105
|
+
words: ["decompress"]
|
|
106
|
+
},
|
|
107
|
+
// 反转
|
|
108
|
+
flip: {
|
|
109
|
+
words: ["reverse"]
|
|
110
|
+
},
|
|
111
|
+
// === 名词类 ===
|
|
112
|
+
// 函数
|
|
113
|
+
Func: {
|
|
114
|
+
words: ["Function"]
|
|
115
|
+
},
|
|
116
|
+
// 值
|
|
117
|
+
Val: {
|
|
118
|
+
words: ["Value"]
|
|
119
|
+
},
|
|
120
|
+
// 数组
|
|
121
|
+
Arr: {
|
|
122
|
+
words: ["Array"]
|
|
123
|
+
},
|
|
124
|
+
// 对象
|
|
125
|
+
Obj: {
|
|
126
|
+
words: ["Object"]
|
|
127
|
+
},
|
|
128
|
+
// 数值
|
|
129
|
+
Num: {
|
|
130
|
+
words: ["Number"]
|
|
131
|
+
},
|
|
132
|
+
// 字符串
|
|
133
|
+
Str: {
|
|
134
|
+
words: ["String"]
|
|
135
|
+
},
|
|
136
|
+
// 字典
|
|
137
|
+
Dict: {
|
|
138
|
+
words: ["Dictionary"]
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
variable: {
|
|
142
|
+
// 连接器
|
|
143
|
+
conn: {
|
|
144
|
+
words: ["connector"]
|
|
145
|
+
},
|
|
146
|
+
// 函数
|
|
147
|
+
func: {
|
|
148
|
+
words: ["function"]
|
|
149
|
+
},
|
|
150
|
+
// 值
|
|
151
|
+
val: {
|
|
152
|
+
words: ["value"]
|
|
153
|
+
},
|
|
154
|
+
// 枚举
|
|
155
|
+
enum: {
|
|
156
|
+
words: ["enumeration"]
|
|
157
|
+
},
|
|
158
|
+
// 数组
|
|
159
|
+
arr: {
|
|
160
|
+
words: ["array"]
|
|
161
|
+
},
|
|
162
|
+
// 对象
|
|
163
|
+
obj: {
|
|
164
|
+
words: ["object"]
|
|
165
|
+
},
|
|
166
|
+
// 数值
|
|
167
|
+
num: {
|
|
168
|
+
words: ["number"]
|
|
169
|
+
},
|
|
170
|
+
// 字符串
|
|
171
|
+
str: {
|
|
172
|
+
words: ["string"]
|
|
173
|
+
},
|
|
174
|
+
bool: {
|
|
175
|
+
words: ["boolean"]
|
|
176
|
+
},
|
|
177
|
+
// 字典
|
|
178
|
+
dict: {
|
|
179
|
+
words: ["dictionary"]
|
|
180
|
+
},
|
|
181
|
+
// 模块
|
|
182
|
+
mod: {
|
|
183
|
+
words: ["module"]
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
// 废话词
|
|
188
|
+
forbidden_words: {
|
|
189
|
+
// 类废话词:禁止在类名中使用的冗余拼接词汇(统一小写)
|
|
190
|
+
// 这些词汇在类名中属于过度设计或冗余描述,即使在某些场景下合理,但作为拼接命名仍然是冗余的
|
|
191
|
+
class: [
|
|
192
|
+
"manager", "handler", "processor", "controller", "service", "provider",
|
|
193
|
+
"factory", "builder", "adapter", "decorator", "proxy", "facade",
|
|
194
|
+
"mediator", "observer", "strategy", "command", "visitor",
|
|
195
|
+
"iterator", "template", "flyweight", "memento", "interpreter",
|
|
196
|
+
"model", "view", "route", "router", "component", "widget", "panel",
|
|
197
|
+
"dialog", "window", "form", "field", "property", "entity"
|
|
198
|
+
// 例如:UserModel → User (直接使用User),UserController → User (直接使用User)
|
|
199
|
+
],
|
|
200
|
+
|
|
201
|
+
// 函数废话词:禁止在函数名中使用的冗余拼接词汇(统一小写)
|
|
202
|
+
// 基于动词+名词组合分析:如果动词已经表达了动作,名词只是数据描述,则名词是废话词
|
|
203
|
+
// 有意义的词通常是拼接get、set、to后能有意义、直接表达的名词,如getUser、toJSON等
|
|
204
|
+
function: [
|
|
205
|
+
// 无意义的数据描述词汇(动词已经表达了动作,这些名词是冗余的)
|
|
206
|
+
"data", "result", "output", "input", "param", "params", "parameter", "parameters",
|
|
207
|
+
"value", "values", "item", "items",
|
|
208
|
+
// 通用处理词汇(动词已经表达了处理,这些名词是冗余的)
|
|
209
|
+
"process", "handler", "processor", "manager", "controller", "service", "provider",
|
|
210
|
+
"factory", "builder", "adapter", "decorator", "proxy", "facade", "mediator",
|
|
211
|
+
"observer", "strategy", "command", "visitor", "iterator", "template",
|
|
212
|
+
"flyweight", "memento", "interpreter",
|
|
213
|
+
// 临时缓存词汇(动词已经表达了操作,这些名词是冗余的)
|
|
214
|
+
"temp", "tmp", "temporary", "cached", "buffered",
|
|
215
|
+
// 计数索引词汇(动词已经表达了计数索引,这些名词是冗余的)
|
|
216
|
+
"idx", "counter",
|
|
217
|
+
// 例如:getData → get(data是冗余),toResult → to(result是冗余)
|
|
218
|
+
// processData → process(data是冗余),handleRequest → handle(request是冗余)
|
|
219
|
+
],
|
|
220
|
+
|
|
221
|
+
// 变量废话词:禁止在变量名中使用的冗余拼接词汇(统一小写)
|
|
222
|
+
// 这些词汇在变量名中属于"不用说也知道"的过度描述
|
|
223
|
+
variable: [
|
|
224
|
+
// 数据类型词:变量本身就有类型,不需要重复说明
|
|
225
|
+
"object", "array", "map", "set", "collection", "container", "instance",
|
|
226
|
+
// 通用数据词:变量本身就是数据/值,不需要重复说明
|
|
227
|
+
"value", "data", "item", "items", "element", "elements", "entry", "entries",
|
|
228
|
+
// 临时状态词:临时变量不需要说明是临时的
|
|
229
|
+
"temp", "tmp", "temporary", "cache", "cached", "buffer", "buffered",
|
|
230
|
+
// 输入输出词:变量本身就有用途,不需要重复说明
|
|
231
|
+
"input", "output", "result", "source", "target", "destination",
|
|
232
|
+
// 计数索引词:变量本身就有计数/索引功能,不需要重复说明
|
|
233
|
+
"count", "index", "idx", "counter", "length", "size", "total", "sum",
|
|
234
|
+
// 引用指针词:变量本身就是引用/指针,不需要重复说明
|
|
235
|
+
"pointer", "reference", "ref", "handle", "handler",
|
|
236
|
+
// 通用描述词:变量本身就是实体,不需要重复说明
|
|
237
|
+
"entity", "record", "row", "column", "cell", "field", "property", "attr", "attribute"
|
|
238
|
+
// 例如:user_list → users(list是冗余),temp_value → temp(value是冗余)
|
|
239
|
+
]
|
|
240
|
+
},
|
|
21
241
|
regex: {
|
|
22
242
|
PascalCase: /^[A-Z][a-zA-Z]*$/, // 大驼峰:大写字母开头,只包含字母。主要用于类名
|
|
23
243
|
camelCase: /^[a-z][a-zA-Z]*$/, // 小驼峰:小写字母开头,只包含字母。主要用于方法名、函数名
|
|
@@ -159,8 +379,10 @@ class Detector {
|
|
|
159
379
|
// 合并默认配置和传入配置
|
|
160
380
|
const merged_cfg = { ...Detector.config };
|
|
161
381
|
if (config && typeof config === "object") {
|
|
382
|
+
// 先合并顶层配置
|
|
162
383
|
Object.keys(config).forEach((key) => {
|
|
163
|
-
if (merged_cfg[key]) {
|
|
384
|
+
if (merged_cfg[key] && typeof merged_cfg[key] === "object" && !Array.isArray(merged_cfg[key])) {
|
|
385
|
+
// 如果是对象配置(如规则配置),则深度合并
|
|
164
386
|
merged_cfg[key] = { ...merged_cfg[key], ...config[key] };
|
|
165
387
|
|
|
166
388
|
// 处理字符串形式的正则表达式
|
|
@@ -183,6 +405,9 @@ class Detector {
|
|
|
183
405
|
merged_cfg[key].regex = null;
|
|
184
406
|
}
|
|
185
407
|
}
|
|
408
|
+
} else {
|
|
409
|
+
// 如果是顶层字段(如recommen),直接覆盖
|
|
410
|
+
merged_cfg[key] = config[key];
|
|
186
411
|
}
|
|
187
412
|
});
|
|
188
413
|
}
|
|
@@ -250,17 +475,20 @@ Detector.prototype._checkName = function (rule_type, name) {
|
|
|
250
475
|
|
|
251
476
|
const errors = [];
|
|
252
477
|
const warnings = [];
|
|
478
|
+
const recommendations = [];
|
|
253
479
|
|
|
254
480
|
this._checkNameLength(name, config, errors);
|
|
255
481
|
this._checkNameFormat(name, rule_type, config, errors);
|
|
256
482
|
this._checkBadWords(name, config, errors);
|
|
257
483
|
this._checkSingleWord(name, rule_type, config, warnings);
|
|
258
484
|
this._checkWordLength(name, rule_type, config, errors);
|
|
485
|
+
this._checkRecommen(name, rule_type, config, recommendations);
|
|
259
486
|
|
|
260
487
|
return {
|
|
261
488
|
valid: errors.length === 0,
|
|
262
489
|
errors: errors,
|
|
263
490
|
warnings: warnings,
|
|
491
|
+
recommendations: recommendations,
|
|
264
492
|
};
|
|
265
493
|
};
|
|
266
494
|
|
|
@@ -317,7 +545,16 @@ Detector.prototype._checkNameFormat = function (
|
|
|
317
545
|
* @private
|
|
318
546
|
*/
|
|
319
547
|
Detector.prototype._checkBadWords = function (name, config, errors) {
|
|
320
|
-
|
|
548
|
+
// 根据配置类型确定代码实体类型
|
|
549
|
+
let type = 'variable'; // 默认变量类型
|
|
550
|
+
|
|
551
|
+
if (config.name.includes('类名')) {
|
|
552
|
+
type = 'class';
|
|
553
|
+
} else if (config.name.includes('函数名') || config.name.includes('方法名')) {
|
|
554
|
+
type = 'function';
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
if (this._hasBadWord(name, type)) {
|
|
321
558
|
errors.push(`${config.name}包含禁止的废话词`);
|
|
322
559
|
}
|
|
323
560
|
};
|
|
@@ -1173,23 +1410,145 @@ Detector.prototype._isConstPat = function (prop_name, value) {
|
|
|
1173
1410
|
};
|
|
1174
1411
|
|
|
1175
1412
|
/**
|
|
1176
|
-
*
|
|
1413
|
+
* 检查是否包含禁止的废话词(拼接命名检测)
|
|
1177
1414
|
* @param {string} name - 名称
|
|
1415
|
+
* @param {string} type - 代码实体类型(class/function/variable)
|
|
1178
1416
|
* @returns {boolean} 是否包含禁止词
|
|
1179
1417
|
* @private
|
|
1180
1418
|
*/
|
|
1181
|
-
Detector.prototype._hasBadWord = function (name) {
|
|
1182
|
-
if (!name) {
|
|
1419
|
+
Detector.prototype._hasBadWord = function (name, type) {
|
|
1420
|
+
if (!name || !type) {
|
|
1183
1421
|
return false;
|
|
1184
1422
|
}
|
|
1185
1423
|
|
|
1186
|
-
const forbidden_words = this.config.forbidden_words || [];
|
|
1424
|
+
const forbidden_words = this.config.forbidden_words[type] || [];
|
|
1425
|
+
const nameLower = name.toLowerCase();
|
|
1426
|
+
|
|
1427
|
+
// 检测拼接命名:名称由多个单词组成,且包含禁止词
|
|
1428
|
+
// 例如:UserManager(包含manager)、DataHandler(包含handler)
|
|
1429
|
+
// 但允许单个单词:Manager、Handler等
|
|
1430
|
+
|
|
1431
|
+
// 如果名称是单个单词,不进行废话词检测
|
|
1432
|
+
if (!this._isCompoundName(name)) {
|
|
1433
|
+
return false;
|
|
1434
|
+
}
|
|
1187
1435
|
|
|
1188
1436
|
return forbidden_words.some((word) =>
|
|
1189
|
-
|
|
1437
|
+
nameLower.includes(word.toLowerCase()),
|
|
1190
1438
|
);
|
|
1191
1439
|
};
|
|
1192
1440
|
|
|
1441
|
+
/**
|
|
1442
|
+
* 检查是否为拼接命名(由多个单词组成)
|
|
1443
|
+
* @param {string} name - 名称
|
|
1444
|
+
* @returns {boolean} 是否为拼接命名
|
|
1445
|
+
* @private
|
|
1446
|
+
*/
|
|
1447
|
+
Detector.prototype._isCompoundName = function (name) {
|
|
1448
|
+
if (!name) {
|
|
1449
|
+
return false;
|
|
1450
|
+
}
|
|
1451
|
+
|
|
1452
|
+
// 检测大驼峰命名(PascalCase):每个单词首字母大写
|
|
1453
|
+
if (/^[A-Z][a-z]+([A-Z][a-z]+)+$/.test(name)) {
|
|
1454
|
+
return true;
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
// 检测小驼峰命名(camelCase):第一个单词小写,后续单词首字母大写
|
|
1458
|
+
if (/^[a-z]+([A-Z][a-z]+)+$/.test(name)) {
|
|
1459
|
+
return true;
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
// 检测蛇形命名(snake_case):单词间以下划线分隔
|
|
1463
|
+
if (/^[a-z]+(_[a-z]+)+$/.test(name)) {
|
|
1464
|
+
return true;
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1467
|
+
// 检测横杠命名(kebab-case):单词间以短横线分隔
|
|
1468
|
+
if (/^[a-z]+(-[a-z]+)+$/.test(name)) {
|
|
1469
|
+
return true;
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1472
|
+
return false;
|
|
1473
|
+
};
|
|
1474
|
+
|
|
1475
|
+
/**
|
|
1476
|
+
* 检查推荐词并生成推荐建议
|
|
1477
|
+
* @param {string} name - 名称
|
|
1478
|
+
* @param {string} rule_type - 规则类型
|
|
1479
|
+
* @param {Object} config - 配置
|
|
1480
|
+
* @param {Array} recommendations - 推荐建议数组
|
|
1481
|
+
* @private
|
|
1482
|
+
*/
|
|
1483
|
+
Detector.prototype._checkRecommen = function (name, rule_type, config, recommendations) {
|
|
1484
|
+
// 只对函数和方法名进行推荐词检测
|
|
1485
|
+
if (rule_type !== "function-name" && rule_type !== "method-name") {
|
|
1486
|
+
return;
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
const recommen_words = this.config.recommen_words.function;
|
|
1490
|
+
|
|
1491
|
+
// 拆分命名中的单词
|
|
1492
|
+
const words = this._splitWords(name, rule_type);
|
|
1493
|
+
|
|
1494
|
+
// 检查每个推荐词类别
|
|
1495
|
+
Object.keys(recommen_words).forEach((category) => {
|
|
1496
|
+
const category_config = recommen_words[category];
|
|
1497
|
+
const category_words = category_config.words || [];
|
|
1498
|
+
|
|
1499
|
+
// 检查拆分后的单词是否包含推荐词类别对应的推荐词
|
|
1500
|
+
let has_target_word = false;
|
|
1501
|
+
words.forEach((word) => {
|
|
1502
|
+
if (category_words.includes(word)) {
|
|
1503
|
+
// 如果单词是目标词(如remove、delete),则生成建议
|
|
1504
|
+
has_target_word = true;
|
|
1505
|
+
}
|
|
1506
|
+
});
|
|
1507
|
+
|
|
1508
|
+
// 如果包含目标词,则生成建议
|
|
1509
|
+
if (has_target_word) {
|
|
1510
|
+
// 检查是否需要生成推荐
|
|
1511
|
+
let should_recommend = false;
|
|
1512
|
+
|
|
1513
|
+
if (this.config.recommen) {
|
|
1514
|
+
// recommen为true:所有符合条件的命名都应该推荐
|
|
1515
|
+
should_recommend = true;
|
|
1516
|
+
} else {
|
|
1517
|
+
// recommen为false:只有当命名中出现单个词汇长度超过指定字符或命名总长度超过限制时才推荐
|
|
1518
|
+
const has_long_word = words.some(word => word.length > (config.single_word_len || 8));
|
|
1519
|
+
const has_long_name = name.length > config.max;
|
|
1520
|
+
|
|
1521
|
+
should_recommend = has_long_word || has_long_name;
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
if (should_recommend) {
|
|
1525
|
+
// 生成推荐建议:将目标词替换为推荐类别词
|
|
1526
|
+
const suggestions = category_words.map((word) => {
|
|
1527
|
+
// 智能替换:保持原始大小写格式
|
|
1528
|
+
const regex = new RegExp(word, 'gi');
|
|
1529
|
+
return name.replace(regex, (match) => {
|
|
1530
|
+
// 保持原始大小写格式
|
|
1531
|
+
if (match === match.toUpperCase()) {
|
|
1532
|
+
return category.toUpperCase();
|
|
1533
|
+
} else if (match[0] === match[0].toUpperCase()) {
|
|
1534
|
+
return category[0].toUpperCase() + category.slice(1);
|
|
1535
|
+
} else {
|
|
1536
|
+
return category;
|
|
1537
|
+
}
|
|
1538
|
+
});
|
|
1539
|
+
});
|
|
1540
|
+
|
|
1541
|
+
recommendations.push({
|
|
1542
|
+
original: name,
|
|
1543
|
+
category: category,
|
|
1544
|
+
suggestions: suggestions,
|
|
1545
|
+
message: `检测到"${category_words.join('、')}",推荐使用: ${suggestions.join(', ')}`
|
|
1546
|
+
});
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
});
|
|
1550
|
+
};
|
|
1551
|
+
|
|
1193
1552
|
/**
|
|
1194
1553
|
* 检测名称是否符合规范
|
|
1195
1554
|
* @param {string} name - 名称
|
|
@@ -1256,7 +1615,7 @@ const class_name_rule = {
|
|
|
1256
1615
|
docs: {
|
|
1257
1616
|
description: "类名必须使用大驼峰命名法(PascalCase)且优先使用单个单词",
|
|
1258
1617
|
category: "Stylistic Issues",
|
|
1259
|
-
|
|
1618
|
+
recommen: true,
|
|
1260
1619
|
},
|
|
1261
1620
|
schema: [
|
|
1262
1621
|
{
|
|
@@ -1304,7 +1663,7 @@ const function_name_rule = {
|
|
|
1304
1663
|
docs: {
|
|
1305
1664
|
description: "函数名必须使用小驼峰命名法(camelCase)且优先使用单个单词",
|
|
1306
1665
|
category: "Stylistic Issues",
|
|
1307
|
-
|
|
1666
|
+
recommen: true,
|
|
1308
1667
|
},
|
|
1309
1668
|
schema: [
|
|
1310
1669
|
{
|
|
@@ -1371,7 +1730,7 @@ const method_name_rule = {
|
|
|
1371
1730
|
docs: {
|
|
1372
1731
|
description: "方法名必须使用小驼峰命名法(camelCase)且优先使用单个单词",
|
|
1373
1732
|
category: "Stylistic Issues",
|
|
1374
|
-
|
|
1733
|
+
recommen: true,
|
|
1375
1734
|
},
|
|
1376
1735
|
schema: [
|
|
1377
1736
|
{
|
|
@@ -1436,7 +1795,7 @@ const variable_name_rule = {
|
|
|
1436
1795
|
docs: {
|
|
1437
1796
|
description: "变量名必须使用小写蛇形命名法(snake_case)",
|
|
1438
1797
|
category: "Stylistic Issues",
|
|
1439
|
-
|
|
1798
|
+
recommen: true,
|
|
1440
1799
|
},
|
|
1441
1800
|
schema: [
|
|
1442
1801
|
{
|
|
@@ -1460,7 +1819,8 @@ const variable_name_rule = {
|
|
|
1460
1819
|
function isRealConstant(node) {
|
|
1461
1820
|
// 真正的常量特征:
|
|
1462
1821
|
// 1. 在模块顶层作用域(不在函数或块内)
|
|
1463
|
-
// 2.
|
|
1822
|
+
// 2. 名称符合常量命名模式(全大写或大写蛇形)
|
|
1823
|
+
// 3. 不是模块导入(避免将require导入识别为常量)
|
|
1464
1824
|
|
|
1465
1825
|
// 检查是否在模块顶层
|
|
1466
1826
|
let scope_node = node;
|
|
@@ -1476,9 +1836,23 @@ const variable_name_rule = {
|
|
|
1476
1836
|
}
|
|
1477
1837
|
}
|
|
1478
1838
|
|
|
1479
|
-
//
|
|
1839
|
+
// 检查是否是模块导入(避免将require导入识别为常量)
|
|
1840
|
+
if (node.init &&
|
|
1841
|
+
(node.init.type === "CallExpression" &&
|
|
1842
|
+
node.init.callee &&
|
|
1843
|
+
node.init.callee.name === "require")) {
|
|
1844
|
+
return false; // 这是模块导入,不是真正的常量
|
|
1845
|
+
}
|
|
1846
|
+
|
|
1847
|
+
// 检查名称是否符合常量命名模式
|
|
1480
1848
|
const name = node.id.name;
|
|
1481
|
-
|
|
1849
|
+
|
|
1850
|
+
// 常量命名模式:全大写或大写蛇形
|
|
1851
|
+
const is_uppercase = /^[A-Z][A-Z0-9]*$/.test(name); // 全大写:PORT, DEBUG
|
|
1852
|
+
const is_upper_snake = /^[A-Z][A-Z0-9_]*(_[A-Z0-9]+)*$/.test(name); // 大写蛇形:API_BASE_URL
|
|
1853
|
+
|
|
1854
|
+
// 只有符合常量命名模式的才被认为是真正的常量
|
|
1855
|
+
return is_uppercase || is_upper_snake;
|
|
1482
1856
|
}
|
|
1483
1857
|
|
|
1484
1858
|
return {
|
|
@@ -1489,6 +1863,89 @@ const variable_name_rule = {
|
|
|
1489
1863
|
return; // 这是真正的常量,由常量规则处理
|
|
1490
1864
|
}
|
|
1491
1865
|
|
|
1866
|
+
// 检查是否是函数声明(由函数名规则处理,这里跳过)
|
|
1867
|
+
if (node.init &&
|
|
1868
|
+
(node.init.type === "FunctionExpression" ||
|
|
1869
|
+
node.init.type === "ArrowFunctionExpression")) {
|
|
1870
|
+
// 这是函数声明,由函数名规则处理,这里跳过避免重复检测
|
|
1871
|
+
return;
|
|
1872
|
+
}
|
|
1873
|
+
|
|
1874
|
+
// 检查是否是类实例
|
|
1875
|
+
if (node.init &&
|
|
1876
|
+
node.init.type === "NewExpression" &&
|
|
1877
|
+
node.init.callee &&
|
|
1878
|
+
node.init.callee.type === "Identifier" &&
|
|
1879
|
+
/^[A-Z][a-zA-Z]*$/.test(node.init.callee.name)) {
|
|
1880
|
+
// 这是类实例,应该由变量名规则处理(类实例是变量,不是类)
|
|
1881
|
+
const class_instance_name = node.id.name;
|
|
1882
|
+
const detector = new Detector({ "variable-name": options });
|
|
1883
|
+
const result = detector.checkName(class_instance_name, "variable-name");
|
|
1884
|
+
|
|
1885
|
+
if (!result.valid) {
|
|
1886
|
+
result.errors.forEach((error) => {
|
|
1887
|
+
context.report({
|
|
1888
|
+
node: node.id,
|
|
1889
|
+
message: `类实例名"${class_instance_name}"不符合规范: ${error}`,
|
|
1890
|
+
});
|
|
1891
|
+
});
|
|
1892
|
+
}
|
|
1893
|
+
return;
|
|
1894
|
+
}
|
|
1895
|
+
|
|
1896
|
+
// 检查是否是模块导入
|
|
1897
|
+
if (node.init &&
|
|
1898
|
+
node.init.type === "CallExpression" &&
|
|
1899
|
+
node.init.callee &&
|
|
1900
|
+
node.init.callee.name === "require") {
|
|
1901
|
+
// 这是模块导入,应用模块导入命名规则
|
|
1902
|
+
const module_name = node.id.name;
|
|
1903
|
+
|
|
1904
|
+
// 智能判断模块导入的命名风格
|
|
1905
|
+
if (/^[A-Z][a-zA-Z]*$/.test(module_name)) {
|
|
1906
|
+
// 类/构造函数导入:Koa, Express - 应该使用PascalCase
|
|
1907
|
+
const detector = new Detector({ "class-name": options });
|
|
1908
|
+
const result = detector.checkName(module_name, "class-name");
|
|
1909
|
+
|
|
1910
|
+
if (!result.valid) {
|
|
1911
|
+
result.errors.forEach((error) => {
|
|
1912
|
+
context.report({
|
|
1913
|
+
node: node.id,
|
|
1914
|
+
message: `模块导入名"${module_name}"不符合规范: ${error}`,
|
|
1915
|
+
});
|
|
1916
|
+
});
|
|
1917
|
+
}
|
|
1918
|
+
} else if (/^[a-z][a-zA-Z]*$/.test(module_name)) {
|
|
1919
|
+
// 默认导出导入:express, config - 应该使用camelCase
|
|
1920
|
+
const detector = new Detector({ "function-name": options });
|
|
1921
|
+
const result = detector.checkName(module_name, "function-name");
|
|
1922
|
+
|
|
1923
|
+
if (!result.valid) {
|
|
1924
|
+
result.errors.forEach((error) => {
|
|
1925
|
+
context.report({
|
|
1926
|
+
node: node.id,
|
|
1927
|
+
message: `模块导入名"${module_name}"不符合规范: ${error}`,
|
|
1928
|
+
});
|
|
1929
|
+
});
|
|
1930
|
+
}
|
|
1931
|
+
} else {
|
|
1932
|
+
// 其他情况(如path, fs) - 使用变量名规则
|
|
1933
|
+
const detector = new Detector({ "variable-name": options });
|
|
1934
|
+
const result = detector.checkName(module_name, "variable-name");
|
|
1935
|
+
|
|
1936
|
+
if (!result.valid) {
|
|
1937
|
+
result.errors.forEach((error) => {
|
|
1938
|
+
context.report({
|
|
1939
|
+
node: node.id,
|
|
1940
|
+
message: `模块导入名"${module_name}"不符合规范: ${error}`,
|
|
1941
|
+
});
|
|
1942
|
+
});
|
|
1943
|
+
}
|
|
1944
|
+
}
|
|
1945
|
+
return;
|
|
1946
|
+
}
|
|
1947
|
+
|
|
1948
|
+
// 真正的变量声明
|
|
1492
1949
|
const variable_name = node.id.name;
|
|
1493
1950
|
const detector = new Detector({ "variable-name": options });
|
|
1494
1951
|
const result = detector.checkName(variable_name, "variable-name");
|
|
@@ -1516,7 +1973,7 @@ const constant_name_rule = {
|
|
|
1516
1973
|
docs: {
|
|
1517
1974
|
description: "常量名必须使用大写蛇形命名法(UPPER_SNAKE_CASE)",
|
|
1518
1975
|
category: "Stylistic Issues",
|
|
1519
|
-
|
|
1976
|
+
recommen: true,
|
|
1520
1977
|
},
|
|
1521
1978
|
schema: [
|
|
1522
1979
|
{
|
|
@@ -1540,8 +1997,8 @@ const constant_name_rule = {
|
|
|
1540
1997
|
function isRealConstant(node) {
|
|
1541
1998
|
// 真正的常量特征:
|
|
1542
1999
|
// 1. 在模块顶层作用域(不在函数或块内)
|
|
1543
|
-
// 2.
|
|
1544
|
-
// 3.
|
|
2000
|
+
// 2. 名称符合常量命名模式(全大写或大写蛇形)
|
|
2001
|
+
// 3. 不是模块导入(避免将require导入识别为常量)
|
|
1545
2002
|
|
|
1546
2003
|
// 检查是否在模块顶层
|
|
1547
2004
|
let scope_node = node;
|
|
@@ -1557,9 +2014,23 @@ const constant_name_rule = {
|
|
|
1557
2014
|
}
|
|
1558
2015
|
}
|
|
1559
2016
|
|
|
1560
|
-
//
|
|
2017
|
+
// 检查是否是模块导入(避免将require导入识别为常量)
|
|
2018
|
+
if (node.init &&
|
|
2019
|
+
(node.init.type === "CallExpression" &&
|
|
2020
|
+
node.init.callee &&
|
|
2021
|
+
node.init.callee.name === "require")) {
|
|
2022
|
+
return false; // 这是模块导入,不是真正的常量
|
|
2023
|
+
}
|
|
2024
|
+
|
|
2025
|
+
// 检查名称是否符合常量命名模式
|
|
1561
2026
|
const name = node.id.name;
|
|
1562
|
-
|
|
2027
|
+
|
|
2028
|
+
// 常量命名模式:全大写或大写蛇形
|
|
2029
|
+
const is_uppercase = /^[A-Z][A-Z0-9]*$/.test(name); // 全大写:PORT, DEBUG
|
|
2030
|
+
const is_upper_snake = /^[A-Z][A-Z0-9_]*(_[A-Z0-9]+)*$/.test(name); // 大写蛇形:API_BASE_URL
|
|
2031
|
+
|
|
2032
|
+
// 只有符合常量命名模式的才被认为是真正的常量
|
|
2033
|
+
return is_uppercase || is_upper_snake;
|
|
1563
2034
|
}
|
|
1564
2035
|
|
|
1565
2036
|
return {
|
|
@@ -1595,7 +2066,7 @@ const param_name_rule = {
|
|
|
1595
2066
|
docs: {
|
|
1596
2067
|
description: "入参名必须使用小写蛇形命名法(snake_case)",
|
|
1597
2068
|
category: "Stylistic Issues",
|
|
1598
|
-
|
|
2069
|
+
recommen: true,
|
|
1599
2070
|
},
|
|
1600
2071
|
schema: [
|
|
1601
2072
|
{
|
|
@@ -1664,7 +2135,7 @@ const prop_name_rule = {
|
|
|
1664
2135
|
docs: {
|
|
1665
2136
|
description: "属性名必须使用小写蛇形命名法(snake_case)",
|
|
1666
2137
|
category: "Stylistic Issues",
|
|
1667
|
-
|
|
2138
|
+
recommen: true,
|
|
1668
2139
|
},
|
|
1669
2140
|
schema: [
|
|
1670
2141
|
{
|
|
@@ -1726,7 +2197,7 @@ const private_method_rule = {
|
|
|
1726
2197
|
docs: {
|
|
1727
2198
|
description: "私有方法必须以单下划线开头,后跟小驼峰命名或小写单词",
|
|
1728
2199
|
category: "Stylistic Issues",
|
|
1729
|
-
|
|
2200
|
+
recommen: true,
|
|
1730
2201
|
},
|
|
1731
2202
|
schema: [
|
|
1732
2203
|
{
|
|
@@ -1779,7 +2250,7 @@ const private_variable_rule = {
|
|
|
1779
2250
|
docs: {
|
|
1780
2251
|
description: "私有变量必须以单下划线开头,后跟小写蛇形命名或小写单词",
|
|
1781
2252
|
category: "Stylistic Issues",
|
|
1782
|
-
|
|
2253
|
+
recommen: true,
|
|
1783
2254
|
},
|
|
1784
2255
|
schema: [
|
|
1785
2256
|
{
|
|
@@ -1832,7 +2303,7 @@ const instance_property_rule = {
|
|
|
1832
2303
|
docs: {
|
|
1833
2304
|
description: "实例属性赋值必须符合命名规范",
|
|
1834
2305
|
category: "Stylistic Issues",
|
|
1835
|
-
|
|
2306
|
+
recommen: true,
|
|
1836
2307
|
},
|
|
1837
2308
|
schema: [
|
|
1838
2309
|
{
|
|
@@ -1888,7 +2359,7 @@ const prototype_method_rule = {
|
|
|
1888
2359
|
docs: {
|
|
1889
2360
|
description: "原型方法名必须使用小驼峰命名法(camelCase)且优先使用单个单词",
|
|
1890
2361
|
category: "Stylistic Issues",
|
|
1891
|
-
|
|
2362
|
+
recommen: true,
|
|
1892
2363
|
},
|
|
1893
2364
|
schema: [
|
|
1894
2365
|
{
|
|
@@ -1917,15 +2388,10 @@ const prototype_method_rule = {
|
|
|
1917
2388
|
node.left.object.property.type === "Identifier" &&
|
|
1918
2389
|
node.left.object.property.name === "prototype" &&
|
|
1919
2390
|
node.left.property.type === "Identifier" &&
|
|
1920
|
-
(node.right.type === "FunctionExpression" ||
|
|
1921
|
-
|
|
2391
|
+
(node.right.type === "FunctionExpression" ||
|
|
2392
|
+
node.right.type === "ArrowFunctionExpression")
|
|
1922
2393
|
) {
|
|
1923
2394
|
const method_name = node.left.property.name;
|
|
1924
|
-
|
|
1925
|
-
// 跳过私有方法的检测(私有方法由private-naming规则处理)
|
|
1926
|
-
if (method_name.startsWith("_")) {
|
|
1927
|
-
return;
|
|
1928
|
-
}
|
|
1929
2395
|
|
|
1930
2396
|
// 跳过JavaScript内置特殊方法名
|
|
1931
2397
|
const builtin_methods = [
|
|
@@ -1938,8 +2404,10 @@ const prototype_method_rule = {
|
|
|
1938
2404
|
return;
|
|
1939
2405
|
}
|
|
1940
2406
|
|
|
1941
|
-
|
|
1942
|
-
const
|
|
2407
|
+
// 根据方法名是否以下划线开头,选择不同的检测规则
|
|
2408
|
+
const rule_name = method_name.startsWith("_") ? "private-method-naming" : "method-name";
|
|
2409
|
+
const detector = new Detector({ [rule_name]: options });
|
|
2410
|
+
const result = detector.checkName(method_name, rule_name);
|
|
1943
2411
|
|
|
1944
2412
|
if (!result.valid) {
|
|
1945
2413
|
result.errors.forEach((error) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mm_eslint",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.9",
|
|
4
4
|
"description": "ESLint plugin for naming conventions - PascalCase, camelCase, snake_case, and UPPER_SNAKE_CASE naming rules",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"keywords": [
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"eslint": ">=8.0.0"
|
|
33
33
|
},
|
|
34
34
|
"scripts": {
|
|
35
|
-
"test": "node
|
|
35
|
+
"test": "node tests/test_new_recommen_words.js",
|
|
36
36
|
"lint": "npx eslint . --config eslint.config.js"
|
|
37
37
|
},
|
|
38
38
|
"files": [
|