mm_eslint 1.1.3 → 1.1.5

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 (2) hide show
  1. package/index.js +205 -76
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -184,6 +184,11 @@ class Detector {
184
184
  }
185
185
  }
186
186
  },
187
+ // 私有方法前缀列表:以这些前缀开头的方法名应该被检测为私有方法
188
+ private_method_prefixes: [
189
+ 'setup', 'init', 'internal', 'private', 'helper', 'util'
190
+ ],
191
+
187
192
  // 废话词
188
193
  forbidden_words: {
189
194
  // 类废话词:禁止在类名中使用的冗余拼接词汇(统一小写)
@@ -1777,36 +1782,55 @@ const method_name_rule = {
1777
1782
  },
1778
1783
  create(context) {
1779
1784
  const options = context.options[0] || {};
1780
- return {
1781
- MethodDefinition(node) {
1782
- const method_name = node.key.name;
1783
-
1784
- // 跳过私有方法的检测(私有方法由private-naming规则处理)
1785
- if (method_name.startsWith("_")) {
1786
- return;
1787
- }
1785
+
1786
+ function checkMethodName(node, method_name) {
1787
+ // 跳过私有方法的检测(私有方法由private-naming规则处理)
1788
+ if (method_name.startsWith("_")) {
1789
+ return;
1790
+ }
1788
1791
 
1789
- // 跳过JavaScript内置特殊方法名
1790
- const builtin_methods = [
1791
- "constructor",
1792
- "toString",
1793
- "valueOf",
1794
- "toJSON",
1795
- ];
1796
- if (builtin_methods.includes(method_name)) {
1797
- return;
1798
- }
1792
+ // 跳过JavaScript内置特殊方法名
1793
+ const builtin_methods = [
1794
+ "constructor",
1795
+ "toString",
1796
+ "valueOf",
1797
+ "toJSON",
1798
+ ];
1799
+ if (builtin_methods.includes(method_name)) {
1800
+ return;
1801
+ }
1799
1802
 
1800
- const detector = new Detector({ "method-name": options });
1801
- const result = detector.checkName(method_name, "method-name");
1803
+ const detector = new Detector({ "method-name": options });
1804
+ const result = detector.checkName(method_name, "method-name");
1802
1805
 
1803
- if (!result.valid) {
1804
- result.errors.forEach((error) => {
1805
- context.report({
1806
- node: node.key,
1807
- message: `方法名"${method_name}"不符合规范: ${error}`,
1808
- });
1806
+ if (!result.valid) {
1807
+ result.errors.forEach((error) => {
1808
+ context.report({
1809
+ node: node.key || node,
1810
+ message: `方法名"${method_name}"不符合规范: ${error}`,
1809
1811
  });
1812
+ });
1813
+ }
1814
+ }
1815
+
1816
+ return {
1817
+ // 处理类中的方法
1818
+ MethodDefinition(node) {
1819
+ checkMethodName(node, node.key.name);
1820
+ },
1821
+
1822
+ // 处理对象字面量中的方法
1823
+ Property(node) {
1824
+ // 检查是否是方法(函数表达式或箭头函数或方法简写)
1825
+ if (node.key.type === "Identifier" && !node.key.name.startsWith("_")) {
1826
+ const is_method = node.value &&
1827
+ (node.value.type === "FunctionExpression" ||
1828
+ node.value.type === "ArrowFunctionExpression" ||
1829
+ (node.method === true)); // 方法简写语法
1830
+
1831
+ if (is_method) {
1832
+ checkMethodName(node, node.key.name);
1833
+ }
1810
1834
  }
1811
1835
  },
1812
1836
  };
@@ -2063,20 +2087,18 @@ const constant_name_rule = {
2063
2087
  return {
2064
2088
  VariableDeclarator(node) {
2065
2089
  if (node.id.type === "Identifier" && node.parent.kind === "const") {
2066
- // 只对真正的常量应用常量命名规则
2067
- if (isRealConstant(node)) {
2068
- const constant_name = node.id.name;
2069
- const detector = new Detector({ "constant-name": options });
2070
- const result = detector.checkName(constant_name, "constant-name");
2090
+ // 对所有const声明应用常量命名规则
2091
+ const constant_name = node.id.name;
2092
+ const detector = new Detector({ "constant-name": options });
2093
+ const result = detector.checkName(constant_name, "constant-name");
2071
2094
 
2072
- if (!result.valid) {
2073
- result.errors.forEach((error) => {
2074
- context.report({
2075
- node: node.id,
2076
- message: `常量名"${constant_name}"不符合规范: ${error}`,
2077
- });
2095
+ if (!result.valid) {
2096
+ result.errors.forEach((error) => {
2097
+ context.report({
2098
+ node: node.id,
2099
+ message: `常量名"${constant_name}"不符合规范: ${error}`,
2078
2100
  });
2079
- }
2101
+ });
2080
2102
  }
2081
2103
  }
2082
2104
  },
@@ -2184,19 +2206,20 @@ const prop_name_rule = {
2184
2206
  const options = context.options[0] || {};
2185
2207
  return {
2186
2208
  Property(node) {
2187
- // 检测类属性、对象字面量属性、模块导出属性
2188
- const is_class_property =
2189
- node.parent &&
2190
- (node.parent.type === "ClassBody" ||
2191
- (node.parent.type === "ObjectExpression" &&
2192
- node.parent.parent &&
2193
- node.parent.parent.type === "ClassDeclaration"));
2194
-
2195
- const is_object_property =
2196
- node.parent && node.parent.type === "ObjectExpression";
2197
-
2198
2209
  // 检测所有非私有属性(不以_开头)
2199
2210
  if (node.key.type === "Identifier" && !node.key.name.startsWith("_")) {
2211
+ // 检查是否是方法(函数表达式或箭头函数或方法简写)
2212
+ const is_method = node.value &&
2213
+ (node.value.type === "FunctionExpression" ||
2214
+ node.value.type === "ArrowFunctionExpression" ||
2215
+ (node.method === true)); // 方法简写语法
2216
+
2217
+ // 如果是方法,跳过属性检测(方法由method-name规则处理)
2218
+ if (is_method) {
2219
+ return;
2220
+ }
2221
+
2222
+ // 如果是真正的属性,使用属性规则检测
2200
2223
  const prop_name = node.key.name;
2201
2224
  const detector = new Detector({ "property-name": options });
2202
2225
  const result = detector._checkPropName(prop_name, node.value);
@@ -2206,6 +2229,7 @@ const prop_name_rule = {
2206
2229
  context.report({
2207
2230
  node: node.key,
2208
2231
  message: `属性名"${prop_name}"不符合规范: ${error}`,
2232
+ ruleId: "naming-convention/property-name",
2209
2233
  });
2210
2234
  });
2211
2235
  }
@@ -2244,23 +2268,81 @@ const private_method_rule = {
2244
2268
  },
2245
2269
  create(context) {
2246
2270
  const options = context.options[0] || {};
2271
+
2272
+ function checkPrivateMethodName(node, method_name) {
2273
+ const detector = new Detector({ "private-method-naming": options });
2274
+ const result = detector.checkName(
2275
+ method_name,
2276
+ "private-method-naming",
2277
+ );
2278
+
2279
+ if (!result.valid) {
2280
+ result.errors.forEach((error) => {
2281
+ context.report({
2282
+ node: node.key || node,
2283
+ message: `私有方法名"${method_name}"不符合规范: ${error}`,
2284
+ });
2285
+ });
2286
+ }
2287
+ }
2288
+
2289
+ // 检测应该是私有方法但没有_前缀的情况
2290
+ function checkMissingPrivatePrefix(node, method_name) {
2291
+ // 使用配置中的私有方法前缀列表
2292
+ const detector = new Detector({ "private-method-naming": options });
2293
+ const private_prefixes = detector.config.private_method_prefixes || [];
2294
+
2295
+ // 判断是否应该是私有方法(基于前缀判断)
2296
+ const should_be_private = private_prefixes.some(prefix => {
2297
+ if (!method_name.toLowerCase().startsWith(prefix.toLowerCase())) {
2298
+ return false;
2299
+ }
2300
+
2301
+ // 额外检查:只有多单词的方法名才需要是私有方法
2302
+ // 例如:init() 可以非私有,但initService() 必须私有
2303
+ const remaining_part = method_name.substring(prefix.length);
2304
+ const is_multi_word = remaining_part.length > 0 &&
2305
+ remaining_part[0].toUpperCase() === remaining_part[0];
2306
+
2307
+ return is_multi_word;
2308
+ });
2309
+
2310
+ if (should_be_private && !method_name.startsWith("_")) {
2311
+ context.report({
2312
+ node: node.key || node,
2313
+ message: `方法名"${method_name}"应该是私有方法,但缺少_前缀`,
2314
+ });
2315
+ }
2316
+ }
2317
+
2247
2318
  return {
2319
+ // 处理类中的私有方法
2248
2320
  MethodDefinition(node) {
2249
2321
  const method_name = node.key.name;
2250
2322
  if (method_name.startsWith("_")) {
2251
- const detector = new Detector({ "private-method-naming": options });
2252
- const result = detector.checkName(
2253
- method_name,
2254
- "private-method-naming",
2255
- );
2256
-
2257
- if (!result.valid) {
2258
- result.errors.forEach((error) => {
2259
- context.report({
2260
- node: node.key,
2261
- message: `私有方法名"${method_name}"不符合规范: ${error}`,
2262
- });
2263
- });
2323
+ checkPrivateMethodName(node, method_name);
2324
+ } else {
2325
+ // 检测应该是私有方法但没有_前缀的情况
2326
+ checkMissingPrivatePrefix(node, method_name);
2327
+ }
2328
+ },
2329
+
2330
+ // 处理对象字面量中的私有方法
2331
+ Property(node) {
2332
+ if (node.key.type === "Identifier") {
2333
+ // 检查是否是方法(函数表达式或箭头函数或方法简写)
2334
+ const is_method = node.value &&
2335
+ (node.value.type === "FunctionExpression" ||
2336
+ node.value.type === "ArrowFunctionExpression" ||
2337
+ (node.method === true)); // 方法简写语法
2338
+
2339
+ if (is_method) {
2340
+ if (node.key.name.startsWith("_")) {
2341
+ checkPrivateMethodName(node, node.key.name);
2342
+ } else {
2343
+ // 检测应该是私有方法但没有_前缀的情况
2344
+ checkMissingPrivatePrefix(node, node.key.name);
2345
+ }
2264
2346
  }
2265
2347
  }
2266
2348
  },
@@ -2300,20 +2382,43 @@ const private_variable_rule = {
2300
2382
  return {
2301
2383
  Property(node) {
2302
2384
  if (node.key.type === "Identifier" && node.key.name.startsWith("_")) {
2303
- const private_name = node.key.name;
2304
- const detector = new Detector({ "private-variable-naming": options });
2305
- const result = detector.checkName(
2306
- private_name,
2307
- "private-variable-naming",
2308
- );
2385
+ // 检查是否是方法(函数表达式或箭头函数)
2386
+ const is_method = node.value &&
2387
+ (node.value.type === "FunctionExpression" ||
2388
+ node.value.type === "ArrowFunctionExpression");
2389
+
2390
+ // 如果是方法,应该使用私有方法规则检测,而不是私有变量规则
2391
+ if (is_method) {
2392
+ const detector = new Detector({ "private-method-naming": options });
2393
+ const result = detector.checkName(
2394
+ node.key.name,
2395
+ "private-method-naming",
2396
+ );
2309
2397
 
2310
- if (!result.valid) {
2311
- result.errors.forEach((error) => {
2312
- context.report({
2313
- node: node.key,
2314
- message: `私有属性名"${private_name}"不符合规范: ${error}`,
2398
+ if (!result.valid) {
2399
+ result.errors.forEach((error) => {
2400
+ context.report({
2401
+ node: node.key,
2402
+ message: `私有方法名"${node.key.name}"不符合规范: ${error}`,
2403
+ });
2315
2404
  });
2316
- });
2405
+ }
2406
+ } else {
2407
+ // 如果是真正的属性,使用私有变量规则检测
2408
+ const detector = new Detector({ "private-variable-naming": options });
2409
+ const result = detector.checkName(
2410
+ node.key.name,
2411
+ "private-variable-naming",
2412
+ );
2413
+
2414
+ if (!result.valid) {
2415
+ result.errors.forEach((error) => {
2416
+ context.report({
2417
+ node: node.key,
2418
+ message: `私有属性名"${node.key.name}"不符合规范: ${error}`,
2419
+ });
2420
+ });
2421
+ }
2317
2422
  }
2318
2423
  }
2319
2424
  },
@@ -2360,8 +2465,9 @@ const instance_property_rule = {
2360
2465
  !node.left.property.name.startsWith("_")
2361
2466
  ) {
2362
2467
  const prop_name = node.left.property.name;
2363
- const detector = new Detector({ "property-name": options });
2364
- const result = detector._checkPropName(prop_name, node.right);
2468
+ // 实例属性应该符合方法命名规范(小驼峰)
2469
+ const detector = new Detector({ "method-name": options });
2470
+ const result = detector.checkName(prop_name, "method-name");
2365
2471
 
2366
2472
  if (!result.valid) {
2367
2473
  result.errors.forEach((error) => {
@@ -2373,6 +2479,29 @@ const instance_property_rule = {
2373
2479
  }
2374
2480
  }
2375
2481
  },
2482
+ // 检测构造函数内的属性声明
2483
+ PropertyDefinition(node) {
2484
+ if (
2485
+ node.parent &&
2486
+ node.parent.type === "ClassBody" &&
2487
+ node.key.type === "Identifier" &&
2488
+ !node.key.name.startsWith("_")
2489
+ ) {
2490
+ const prop_name = node.key.name;
2491
+ // 实例属性应该符合方法命名规范(小驼峰)
2492
+ const detector = new Detector({ "method-name": options });
2493
+ const result = detector.checkName(prop_name, "method-name");
2494
+
2495
+ if (!result.valid) {
2496
+ result.errors.forEach((error) => {
2497
+ context.report({
2498
+ node: node.key,
2499
+ message: `实例属性名"${prop_name}"不符合规范: ${error}`,
2500
+ });
2501
+ });
2502
+ }
2503
+ }
2504
+ },
2376
2505
  };
2377
2506
  },
2378
2507
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mm_eslint",
3
- "version": "1.1.3",
3
+ "version": "1.1.5",
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": [