@atlisp/lint 0.1.0 → 0.1.2

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 (100) hide show
  1. package/README.md +35 -1
  2. package/atlisp-lint.default.json +19 -0
  3. package/dist/atlisp-lint.default.json +19 -0
  4. package/dist/cache.d.ts +4 -0
  5. package/dist/cache.d.ts.map +1 -0
  6. package/dist/cache.js +74 -0
  7. package/dist/cache.js.map +1 -0
  8. package/dist/checks/arg-count.d.ts +3 -0
  9. package/dist/checks/arg-count.d.ts.map +1 -0
  10. package/dist/checks/arg-count.js +120 -0
  11. package/dist/checks/arg-count.js.map +1 -0
  12. package/dist/checks/cond-simplify.d.ts +3 -0
  13. package/dist/checks/cond-simplify.d.ts.map +1 -0
  14. package/dist/checks/cond-simplify.js +42 -0
  15. package/dist/checks/cond-simplify.js.map +1 -0
  16. package/dist/checks/dangerous-calls.d.ts.map +1 -1
  17. package/dist/checks/dangerous-calls.js +9 -7
  18. package/dist/checks/dangerous-calls.js.map +1 -1
  19. package/dist/checks/error-handling.d.ts +3 -0
  20. package/dist/checks/error-handling.d.ts.map +1 -0
  21. package/dist/checks/error-handling.js +53 -0
  22. package/dist/checks/error-handling.js.map +1 -0
  23. package/dist/checks/extra-parens.d.ts +3 -0
  24. package/dist/checks/extra-parens.d.ts.map +1 -0
  25. package/dist/checks/extra-parens.js +42 -0
  26. package/dist/checks/extra-parens.js.map +1 -0
  27. package/dist/checks/function-complexity.d.ts +3 -0
  28. package/dist/checks/function-complexity.d.ts.map +1 -0
  29. package/dist/checks/function-complexity.js +57 -0
  30. package/dist/checks/function-complexity.js.map +1 -0
  31. package/dist/checks/global-naming.d.ts +3 -0
  32. package/dist/checks/global-naming.d.ts.map +1 -0
  33. package/dist/checks/global-naming.js +51 -0
  34. package/dist/checks/global-naming.js.map +1 -0
  35. package/dist/checks/line-length.d.ts +3 -0
  36. package/dist/checks/line-length.d.ts.map +1 -0
  37. package/dist/checks/line-length.js +19 -0
  38. package/dist/checks/line-length.js.map +1 -0
  39. package/dist/checks/missing-doc.d.ts +3 -0
  40. package/dist/checks/missing-doc.d.ts.map +1 -0
  41. package/dist/checks/missing-doc.js +40 -0
  42. package/dist/checks/missing-doc.js.map +1 -0
  43. package/dist/checks/parameter-naming.d.ts +3 -0
  44. package/dist/checks/parameter-naming.d.ts.map +1 -0
  45. package/dist/checks/parameter-naming.js +29 -0
  46. package/dist/checks/parameter-naming.js.map +1 -0
  47. package/dist/checks/strcat-usage.d.ts +3 -0
  48. package/dist/checks/strcat-usage.d.ts.map +1 -0
  49. package/dist/checks/strcat-usage.js +22 -0
  50. package/dist/checks/strcat-usage.js.map +1 -0
  51. package/dist/checks/unused-variable.d.ts +3 -0
  52. package/dist/checks/unused-variable.d.ts.map +1 -0
  53. package/dist/checks/unused-variable.js +50 -0
  54. package/dist/checks/unused-variable.js.map +1 -0
  55. package/dist/config.d.ts +2 -0
  56. package/dist/config.d.ts.map +1 -1
  57. package/dist/config.js +35 -0
  58. package/dist/config.js.map +1 -1
  59. package/dist/disable.d.ts +4 -0
  60. package/dist/disable.d.ts.map +1 -0
  61. package/dist/disable.js +31 -0
  62. package/dist/disable.js.map +1 -0
  63. package/dist/formatters.d.ts +2 -1
  64. package/dist/formatters.d.ts.map +1 -1
  65. package/dist/formatters.js +105 -7
  66. package/dist/formatters.js.map +1 -1
  67. package/dist/index.d.ts.map +1 -1
  68. package/dist/index.js +91 -6
  69. package/dist/index.js.map +1 -1
  70. package/dist/lib/lint-sbcl.lisp +54 -19
  71. package/dist/locale.d.ts.map +1 -1
  72. package/dist/locale.js +34 -0
  73. package/dist/locale.js.map +1 -1
  74. package/dist/rules.d.ts +9 -0
  75. package/dist/rules.d.ts.map +1 -0
  76. package/dist/rules.js +39 -0
  77. package/dist/rules.js.map +1 -0
  78. package/dist/runner.d.ts +2 -0
  79. package/dist/runner.d.ts.map +1 -1
  80. package/dist/runner.js +117 -41
  81. package/dist/runner.js.map +1 -1
  82. package/dist/sbcl.d.ts.map +1 -1
  83. package/dist/sbcl.js +35 -17
  84. package/dist/sbcl.js.map +1 -1
  85. package/dist/types.d.ts +10 -0
  86. package/dist/types.d.ts.map +1 -1
  87. package/dist/validate.d.ts +8 -0
  88. package/dist/validate.d.ts.map +1 -0
  89. package/dist/validate.js +55 -0
  90. package/dist/validate.js.map +1 -0
  91. package/dist/watch.d.ts +9 -0
  92. package/dist/watch.d.ts.map +1 -0
  93. package/dist/watch.js +109 -0
  94. package/dist/watch.js.map +1 -0
  95. package/dist/worker.d.ts +2 -0
  96. package/dist/worker.d.ts.map +1 -0
  97. package/dist/worker.js +72 -0
  98. package/dist/worker.js.map +1 -0
  99. package/lib/lint-sbcl.lisp +54 -19
  100. package/package.json +11 -2
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @atlisp/lint
2
2
 
3
- AutoLISP 静态分析工具 — 括号匹配、安全检查、编码检测、命名规范、SBCL 语法校验。
3
+ AutoLISP 静态分析工具 — 括号匹配、安全检查、编码检测、命名规范、函数复杂度、SBCL 语法校验。
4
4
 
5
5
  ## 安装
6
6
 
@@ -21,6 +21,9 @@ npx @atlisp/lint
21
21
 
22
22
  # 输出 JSON 格式
23
23
  npx @atlisp/lint --format json
24
+
25
+ # 自动修复可修复问题(尾部空格、BOM)
26
+ npx @atlisp/lint --fix
24
27
  ```
25
28
 
26
29
  ## CLI 选项
@@ -33,6 +36,8 @@ npx @atlisp/lint --format json
33
36
  --format <format> 输出格式:default(默认)| json
34
37
  --init 在当前目录生成 atlisp-lint.json
35
38
  --install-hook 安装 git pre-commit hook
39
+ --fix 自动修复尾部空格、UTF-8 BOM 等问题
40
+ --hook-args <args> 自定义 pre-commit hook 参数(配合 --install-hook)
36
41
  ```
37
42
 
38
43
  ## 检查规则
@@ -52,6 +57,11 @@ npx @atlisp/lint --format json
52
57
  | `token_in_url` | warn | URL 中包含 `token=`(凭据泄露) |
53
58
  | `open_without_close` | warn | open/close 数量不匹配(资源泄露) |
54
59
  | `bare_function_names` | warn | defun 缺少命名空间前缀 |
60
+ | `line_length` | warn | 行长度超过限制 |
61
+ | `function_complexity` | warn | 函数行数或嵌套深度超限 |
62
+ | `parameter_naming` | warn | 参数首字母大写 |
63
+ | `unused_variable` | warn | 变量被赋值但未使用 |
64
+ | `missing_doc` | warn | 函数缺少注释说明 |
55
65
  | `trailing_whitespace` | warn | 行尾多余空格 |
56
66
  | `module_registration` | off | 模块文件未注册到 `*modules*` |
57
67
  | `namespace_header` | off | 缺少 `(in-package ...)` 头 |
@@ -65,6 +75,14 @@ npx @atlisp/lint --format json
65
75
  - CL-ism — `#(`、`#\`、`#.` 等 AutoLISP 无效语法
66
76
  - defmacro — 默认不允许,除非文件在允许列表中
67
77
 
78
+ ## 行内忽略
79
+
80
+ 在代码行尾添加注释可以忽略特定规则的检查:
81
+
82
+ ```lisp
83
+ (setq secret "token=abc123") ; atlisp-lint: disable=token_in_url
84
+ ```
85
+
68
86
  ## 配置文件
69
87
 
70
88
  `atlisp-lint.json`:
@@ -88,10 +106,23 @@ npx @atlisp/lint --format json
88
106
  "token_in_url": "warn",
89
107
  "open_without_close": "warn",
90
108
  "bare_function_names": "warn",
109
+ "line_length": "warn",
110
+ "function_complexity": "warn",
111
+ "parameter_naming": "warn",
112
+ "unused_variable": "warn",
113
+ "missing_doc": "warn",
91
114
  "trailing_whitespace": "warn",
92
115
  "module_registration": "off",
93
116
  "namespace_header": "off"
94
117
  },
118
+ "line_length": {
119
+ "max": 100,
120
+ "tab_width": 2
121
+ },
122
+ "function_complexity": {
123
+ "max_lines": 60,
124
+ "max_nesting": 6
125
+ },
95
126
  "cl_syntax": {
96
127
  "keywords": ["&key"]
97
128
  },
@@ -128,6 +159,9 @@ npx @atlisp/lint --format json
128
159
  # 安装 pre-commit hook,每次提交前自动检查暂存文件
129
160
  npx @atlisp/lint --install-hook
130
161
 
162
+ # 带自定义参数的 hook
163
+ npx @atlisp/lint --install-hook --hook-args "--config ci-config.json"
164
+
131
165
  # 手动检查暂存文件
132
166
  npx @atlisp/lint --staged
133
167
  ```
@@ -16,10 +16,29 @@
16
16
  "token_in_url": "warn",
17
17
  "open_without_close": "warn",
18
18
  "bare_function_names": "warn",
19
+ "line_length": "warn",
20
+ "function_complexity": "warn",
21
+ "parameter_naming": "warn",
22
+ "unused_variable": "warn",
23
+ "missing_doc": "warn",
24
+ "error_handling": "warn",
25
+ "global_naming": "warn",
26
+ "extra_parens": "warn",
27
+ "arg_count": "warn",
28
+ "strcat_usage": "warn",
29
+ "cond_simplify": "warn",
19
30
  "trailing_whitespace": "warn",
20
31
  "module_registration": "off",
21
32
  "namespace_header": "off"
22
33
  },
34
+ "line_length": {
35
+ "max": 100,
36
+ "tab_width": 2
37
+ },
38
+ "function_complexity": {
39
+ "max_lines": 60,
40
+ "max_nesting": 6
41
+ },
23
42
  "cl_syntax": {
24
43
  "keywords": ["&key"]
25
44
  },
@@ -16,10 +16,29 @@
16
16
  "token_in_url": "warn",
17
17
  "open_without_close": "warn",
18
18
  "bare_function_names": "warn",
19
+ "line_length": "warn",
20
+ "function_complexity": "warn",
21
+ "parameter_naming": "warn",
22
+ "unused_variable": "warn",
23
+ "missing_doc": "warn",
24
+ "error_handling": "warn",
25
+ "global_naming": "warn",
26
+ "extra_parens": "warn",
27
+ "arg_count": "warn",
28
+ "strcat_usage": "warn",
29
+ "cond_simplify": "warn",
19
30
  "trailing_whitespace": "warn",
20
31
  "module_registration": "off",
21
32
  "namespace_header": "off"
22
33
  },
34
+ "line_length": {
35
+ "max": 100,
36
+ "tab_width": 2
37
+ },
38
+ "function_complexity": {
39
+ "max_lines": 60,
40
+ "max_nesting": 6
41
+ },
23
42
  "cl_syntax": {
24
43
  "keywords": ["&key"]
25
44
  },
@@ -0,0 +1,4 @@
1
+ export declare function isCached(filepath: string, rootDir: string): boolean;
2
+ export declare function markCached(filepath: string, rootDir: string): void;
3
+ export declare function clearCache(rootDir: string): void;
4
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAcA,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAOnE;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CASlE;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAKhD"}
package/dist/cache.js ADDED
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.isCached = isCached;
37
+ exports.markCached = markCached;
38
+ exports.clearCache = clearCache;
39
+ const fs = __importStar(require("fs"));
40
+ const path = __importStar(require("path"));
41
+ const crypto = __importStar(require("crypto"));
42
+ const CACHE_DIR = '.atlisp-lint-cache';
43
+ function getCacheDir(rootDir) {
44
+ return path.join(rootDir, CACHE_DIR);
45
+ }
46
+ function fileHash(content) {
47
+ return crypto.createHash('md5').update(content).digest('hex');
48
+ }
49
+ function isCached(filepath, rootDir) {
50
+ const cacheDir = getCacheDir(rootDir);
51
+ if (!fs.existsSync(cacheDir))
52
+ return false;
53
+ const content = fs.readFileSync(filepath, 'utf-8');
54
+ const hash = fileHash(content);
55
+ const cacheFile = path.join(cacheDir, hash);
56
+ return fs.existsSync(cacheFile);
57
+ }
58
+ function markCached(filepath, rootDir) {
59
+ const cacheDir = getCacheDir(rootDir);
60
+ if (!fs.existsSync(cacheDir)) {
61
+ fs.mkdirSync(cacheDir, { recursive: true });
62
+ }
63
+ const content = fs.readFileSync(filepath, 'utf-8');
64
+ const hash = fileHash(content);
65
+ const cacheFile = path.join(cacheDir, hash);
66
+ fs.writeFileSync(cacheFile, '');
67
+ }
68
+ function clearCache(rootDir) {
69
+ const cacheDir = getCacheDir(rootDir);
70
+ if (fs.existsSync(cacheDir)) {
71
+ fs.rmSync(cacheDir, { recursive: true, force: true });
72
+ }
73
+ }
74
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAcA,4BAOC;AAED,gCASC;AAED,gCAKC;AAvCD,uCAAyB;AACzB,2CAA6B;AAC7B,+CAAiC;AAEjC,MAAM,SAAS,GAAG,oBAAoB,CAAA;AAEtC,SAAS,WAAW,CAAC,OAAe;IAClC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAA;AACtC,CAAC;AAED,SAAS,QAAQ,CAAC,OAAe;IAC/B,OAAO,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AAC/D,CAAC;AAED,SAAgB,QAAQ,CAAC,QAAgB,EAAE,OAAe;IACxD,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,CAAA;IACrC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,KAAK,CAAA;IAC1C,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IAClD,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAA;IAC9B,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;IAC3C,OAAO,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAA;AACjC,CAAC;AAED,SAAgB,UAAU,CAAC,QAAgB,EAAE,OAAe;IAC1D,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,CAAA;IACrC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAC7C,CAAC;IACD,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IAClD,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAA;IAC9B,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;IAC3C,EAAE,CAAC,aAAa,CAAC,SAAS,EAAE,EAAE,CAAC,CAAA;AACjC,CAAC;AAED,SAAgB,UAAU,CAAC,OAAe;IACxC,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,CAAA;IACrC,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;IACvD,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Issue } from '../types';
2
+ export declare function checkArgCount(content: string, file: string): Issue[];
3
+ //# sourceMappingURL=arg-count.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"arg-count.d.ts","sourceRoot":"","sources":["../../src/checks/arg-count.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAUjC,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK,EAAE,CAoFpE"}
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkArgCount = checkArgCount;
4
+ const locale_1 = require("../locale");
5
+ const utils_1 = require("../utils");
6
+ function checkArgCount(content, file) {
7
+ const issues = [];
8
+ const lines = content.split('\n');
9
+ const defuns = [];
10
+ // Collect all defun definitions
11
+ for (let i = 0; i < lines.length; i++) {
12
+ const stripped = (0, utils_1.stripLine)(lines[i]);
13
+ const m = stripped.match(/\(defun\s+(\S+)\s+\(([^)]*)\)/);
14
+ if (m) {
15
+ const all = m[2];
16
+ const slashIdx = all.indexOf('/');
17
+ const paramStr = slashIdx >= 0 ? all.slice(0, slashIdx).trim() : all;
18
+ const params = paramStr.split(/\s+/).filter(Boolean);
19
+ defuns.push({ name: m[1], line: i + 1, paramCount: params.length });
20
+ }
21
+ }
22
+ // Check calls against definitions
23
+ for (const fn of defuns) {
24
+ if (fn.name.startsWith('c:') || fn.name.includes('/'))
25
+ continue;
26
+ if (fn.paramCount === 0)
27
+ continue;
28
+ for (let i = 0; i < lines.length; i++) {
29
+ const stripped = (0, utils_1.stripLine)(lines[i]);
30
+ const re = new RegExp('\\(\\s*' + fn.name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '\\s+');
31
+ // Don't match the definition line
32
+ if (stripped.includes('defun') && stripped.includes(fn.name))
33
+ continue;
34
+ const callMatch = re.exec(stripped);
35
+ if (callMatch) {
36
+ // Collect all text from the call across lines
37
+ let callText = stripped.slice(callMatch.index);
38
+ let parenDepth = 0;
39
+ for (const ch of callText) {
40
+ if (ch === '(')
41
+ parenDepth++;
42
+ else if (ch === ')')
43
+ parenDepth--;
44
+ }
45
+ // If not closed on this line, read next lines
46
+ let lineIdx = i + 1;
47
+ while (parenDepth > 0 && lineIdx < lines.length) {
48
+ const nextStripped = (0, utils_1.stripLine)(lines[lineIdx]);
49
+ callText += ' ' + nextStripped;
50
+ for (const ch of nextStripped) {
51
+ if (ch === '(')
52
+ parenDepth++;
53
+ else if (ch === ')')
54
+ parenDepth--;
55
+ }
56
+ lineIdx++;
57
+ }
58
+ // Extract args: remove the function call prefix
59
+ const afterName = callText.slice(callMatch[0].length - 1); // keep the leading (
60
+ // Find matching closing paren
61
+ let closeIdx = -1;
62
+ let pd = 1;
63
+ for (let j = 0; j < afterName.length; j++) {
64
+ if (afterName[j] === '(')
65
+ pd++;
66
+ else if (afterName[j] === ')') {
67
+ pd--;
68
+ if (pd === 0) {
69
+ closeIdx = j;
70
+ break;
71
+ }
72
+ }
73
+ }
74
+ const argsStr = closeIdx >= 0 ? afterName.slice(0, closeIdx).trim() : afterName.trim();
75
+ if (!argsStr)
76
+ continue;
77
+ // Count space-delimited args at depth 0
78
+ let argCount = 0;
79
+ let depth = 0;
80
+ let inArg = false;
81
+ for (const ch of argsStr) {
82
+ if (ch === '(') {
83
+ depth++;
84
+ if (!inArg) {
85
+ inArg = true;
86
+ }
87
+ }
88
+ else if (ch === ')') {
89
+ depth--;
90
+ if (depth === 0) {
91
+ if (inArg) {
92
+ argCount++;
93
+ inArg = false;
94
+ }
95
+ }
96
+ }
97
+ else if (depth === 0 && (ch === ' ' || ch === '\t')) {
98
+ if (inArg) {
99
+ argCount++;
100
+ inArg = false;
101
+ }
102
+ }
103
+ else if (!inArg) {
104
+ inArg = true;
105
+ }
106
+ }
107
+ if (inArg)
108
+ argCount++;
109
+ if (argCount !== fn.paramCount) {
110
+ issues.push({
111
+ file, line: i + 1, severity: 'warn', rule: 'arg_count',
112
+ message: (0, locale_1.t)('arg_count', fn.name, argCount, fn.paramCount),
113
+ });
114
+ }
115
+ }
116
+ }
117
+ }
118
+ return issues;
119
+ }
120
+ //# sourceMappingURL=arg-count.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"arg-count.js","sourceRoot":"","sources":["../../src/checks/arg-count.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Issue } from '../types';
2
+ export declare function checkCondSimplify(content: string, file: string): Issue[];
3
+ //# sourceMappingURL=cond-simplify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cond-simplify.d.ts","sourceRoot":"","sources":["../../src/checks/cond-simplify.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAIjC,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK,EAAE,CAmCxE"}
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkCondSimplify = checkCondSimplify;
4
+ const locale_1 = require("../locale");
5
+ const utils_1 = require("../utils");
6
+ function checkCondSimplify(content, file) {
7
+ const issues = [];
8
+ const lines = content.split('\n');
9
+ for (let i = 0; i < lines.length; i++) {
10
+ const stripped = (0, utils_1.stripLine)(lines[i]);
11
+ // Match (cond (t ...)) or (cond (expr ...)) - single branch cond
12
+ // A single-branch cond typically looks like: (cond (expr body)) on one line
13
+ const m = stripped.match(/\(cond\s+\(/);
14
+ if (m) {
15
+ // Count how many top-level branches inside this cond
16
+ const condStart = stripped.indexOf('(cond');
17
+ const afterCond = stripped.slice(condStart + 5).trim();
18
+ let branchCount = 0;
19
+ let parenDepth = 0;
20
+ for (const ch of afterCond) {
21
+ if (ch === '(') {
22
+ if (parenDepth === 0)
23
+ branchCount++;
24
+ parenDepth++;
25
+ }
26
+ else if (ch === ')') {
27
+ parenDepth--;
28
+ if (parenDepth < 0)
29
+ break;
30
+ }
31
+ }
32
+ if (branchCount === 1) {
33
+ issues.push({
34
+ file, line: i + 1, severity: 'warn', rule: 'cond_simplify',
35
+ message: (0, locale_1.t)('cond_simplify'),
36
+ });
37
+ }
38
+ }
39
+ }
40
+ return issues;
41
+ }
42
+ //# sourceMappingURL=cond-simplify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cond-simplify.js","sourceRoot":"","sources":["../../src/checks/cond-simplify.ts"],"names":[],"mappings":";;AAIA,8CAmCC;AAtCD,sCAA8B;AAC9B,oCAAqC;AAErC,SAAgB,iBAAiB,CAAC,OAAe,EAAE,IAAY;IAC7D,MAAM,MAAM,GAAY,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAElC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,QAAQ,GAAG,IAAA,iBAAS,EAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACrC,iEAAiE;QACjE,4EAA4E;QAC5E,MAAM,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QACxC,IAAI,CAAC,EAAE,CAAC;YACN,qDAAqD;YACrD,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAC5C,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YACvD,IAAI,WAAW,GAAG,CAAC,CAAC;YACpB,IAAI,UAAU,GAAG,CAAC,CAAC;YAEnB,KAAK,MAAM,EAAE,IAAI,SAAS,EAAE,CAAC;gBAC3B,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;oBACf,IAAI,UAAU,KAAK,CAAC;wBAAE,WAAW,EAAE,CAAC;oBACpC,UAAU,EAAE,CAAC;gBACf,CAAC;qBAAM,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;oBACtB,UAAU,EAAE,CAAC;oBACb,IAAI,UAAU,GAAG,CAAC;wBAAE,MAAM;gBAC5B,CAAC;YACH,CAAC;YAED,IAAI,WAAW,KAAK,CAAC,EAAE,CAAC;gBACtB,MAAM,CAAC,IAAI,CAAC;oBACV,IAAI,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe;oBAC1D,OAAO,EAAE,IAAA,UAAC,EAAC,eAAe,CAAC;iBAC5B,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"dangerous-calls.d.ts","sourceRoot":"","sources":["../../src/checks/dangerous-calls.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AA0BvD,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,GAC1D,KAAK,EAAE,CAsBT"}
1
+ {"version":3,"file":"dangerous-calls.d.ts","sourceRoot":"","sources":["../../src/checks/dangerous-calls.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AA2BvD,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,GAC1D,KAAK,EAAE,CAwBT"}
@@ -4,8 +4,8 @@ exports.checkDangerousCalls = checkDangerousCalls;
4
4
  const utils_1 = require("../utils");
5
5
  const locale_1 = require("../locale");
6
6
  const PATTERNS = [
7
- { rule: 'quit', check: l => /\bquit\b/.test(l), key: 'quit' },
8
- { rule: 'exit', check: l => /\bexit\b/.test(l), key: 'exit' },
7
+ { rule: 'quit', check: l => /\bquit\b/.test(l), key: 'quit', useStripped: true },
8
+ { rule: 'exit', check: l => /\bexit\b/.test(l), key: 'exit', useStripped: true },
9
9
  { rule: 'command_shell', check: l => /\(command\s+"shell"\s/.test(l), key: 'command_shell' },
10
10
  { rule: 'startapp', check: l => /\bstartapp\b/.test(l), key: 'startapp' },
11
11
  { rule: 'vl_registry_write', check: l => /\bvl-registry-write\b/.test(l), key: 'vl_registry_write' },
@@ -22,15 +22,17 @@ function checkDangerousCalls(content, file, config) {
22
22
  const lines = content.split('\n');
23
23
  for (let lineno = 1; lineno <= lines.length; lineno++) {
24
24
  const line = lines[lineno - 1];
25
- // Strip comments only, keep strings intact
26
- const stripped = (0, utils_1.stripLineRaw)(line).trim();
27
- if (!stripped)
28
- continue;
25
+ // Two versions: without strings (for bare word checks) and with strings (for quoted arg checks)
26
+ const strippedCode = (0, utils_1.stripLine)(line).trim(); // strings removed
27
+ const strippedRaw = (0, utils_1.stripLineRaw)(line).trim(); // strings preserved
29
28
  for (const p of PATTERNS) {
30
29
  const configuredSeverity = config[p.key];
31
30
  if (configuredSeverity === 'off')
32
31
  continue;
33
- if (p.check(stripped)) {
32
+ const testStr = p.useStripped ? strippedCode : strippedRaw;
33
+ if (!testStr)
34
+ continue;
35
+ if (p.check(testStr)) {
34
36
  issues.push({
35
37
  file, line: lineno, severity: configuredSeverity, rule: p.rule,
36
38
  message: (0, locale_1.t)(MESSAGE_KEYS[p.rule]),
@@ -1 +1 @@
1
- {"version":3,"file":"dangerous-calls.js","sourceRoot":"","sources":["../../src/checks/dangerous-calls.ts"],"names":[],"mappings":";;AA0BA,kDAwBC;AAjDD,oCAAwC;AACxC,sCAA8B;AAQ9B,MAAM,QAAQ,GAAc;IAC1B,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE;IAC7D,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE;IAC7D,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,eAAe,EAAE;IAC5F,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE;IACzE,EAAE,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,mBAAmB,EAAE;CACrG,CAAC;AAEF,MAAM,YAAY,GAA2B;IAC3C,IAAI,EAAE,gBAAgB;IACtB,IAAI,EAAE,gBAAgB;IACtB,aAAa,EAAE,yBAAyB;IACxC,QAAQ,EAAE,oBAAoB;IAC9B,iBAAiB,EAAE,6BAA6B;CACjD,CAAC;AAEF,SAAgB,mBAAmB,CACjC,OAAe,EAAE,IAAY,EAAE,MAA4B;IAE3D,MAAM,MAAM,GAAY,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAElC,KAAK,IAAI,MAAM,GAAG,CAAC,EAAE,MAAM,IAAI,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;QACtD,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC/B,2CAA2C;QAC3C,MAAM,QAAQ,GAAG,IAAA,oBAAY,EAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;QAC3C,IAAI,CAAC,QAAQ;YAAE,SAAS;QAExB,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;YACzB,MAAM,kBAAkB,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YACzC,IAAI,kBAAkB,KAAK,KAAK;gBAAE,SAAS;YAC3C,IAAI,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACtB,MAAM,CAAC,IAAI,CAAC;oBACV,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI;oBAC9D,OAAO,EAAE,IAAA,UAAC,EAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;iBACjC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"dangerous-calls.js","sourceRoot":"","sources":["../../src/checks/dangerous-calls.ts"],"names":[],"mappings":";;AA2BA,kDA0BC;AApDD,oCAAmD;AACnD,sCAA8B;AAS9B,MAAM,QAAQ,GAAc;IAC1B,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE;IAChF,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE;IAChF,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,eAAe,EAAE;IAC5F,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE;IACzE,EAAE,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,mBAAmB,EAAE;CACrG,CAAC;AAEF,MAAM,YAAY,GAA2B;IAC3C,IAAI,EAAE,gBAAgB;IACtB,IAAI,EAAE,gBAAgB;IACtB,aAAa,EAAE,yBAAyB;IACxC,QAAQ,EAAE,oBAAoB;IAC9B,iBAAiB,EAAE,6BAA6B;CACjD,CAAC;AAEF,SAAgB,mBAAmB,CACjC,OAAe,EAAE,IAAY,EAAE,MAA4B;IAE3D,MAAM,MAAM,GAAY,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAElC,KAAK,IAAI,MAAM,GAAG,CAAC,EAAE,MAAM,IAAI,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;QACtD,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC/B,gGAAgG;QAChG,MAAM,YAAY,GAAG,IAAA,iBAAS,EAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAG,kBAAkB;QACjE,MAAM,WAAW,GAAG,IAAA,oBAAY,EAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,oBAAoB;QAEnE,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;YACzB,MAAM,kBAAkB,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YACzC,IAAI,kBAAkB,KAAK,KAAK;gBAAE,SAAS;YAC3C,MAAM,OAAO,GAAG,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC;YAC3D,IAAI,CAAC,OAAO;gBAAE,SAAS;YACvB,IAAI,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;gBACrB,MAAM,CAAC,IAAI,CAAC;oBACV,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI;oBAC9D,OAAO,EAAE,IAAA,UAAC,EAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;iBACjC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Issue } from '../types';
2
+ export declare function checkErrorHandling(content: string, file: string): Issue[];
3
+ //# sourceMappingURL=error-handling.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-handling.d.ts","sourceRoot":"","sources":["../../src/checks/error-handling.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAIjC,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK,EAAE,CAgDzE"}
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkErrorHandling = checkErrorHandling;
4
+ const locale_1 = require("../locale");
5
+ const utils_1 = require("../utils");
6
+ function checkErrorHandling(content, file) {
7
+ const issues = [];
8
+ const lines = content.split('\n');
9
+ let inDefun = false;
10
+ let defunName = '';
11
+ let defunStart = 0;
12
+ let defunText = '';
13
+ let hasErrorHandler = false;
14
+ for (let i = 0; i < lines.length; i++) {
15
+ const stripped = (0, utils_1.stripLine)(lines[i]);
16
+ if (!inDefun) {
17
+ const m = stripped.match(/\(defun\s+(\S+)/);
18
+ if (m) {
19
+ inDefun = true;
20
+ defunName = m[1];
21
+ defunStart = i + 1;
22
+ defunText = '';
23
+ hasErrorHandler = false;
24
+ }
25
+ }
26
+ if (inDefun) {
27
+ defunText += stripped + '\n';
28
+ if (stripped.includes('*error*'))
29
+ hasErrorHandler = true;
30
+ // Check for depth returning to 0 (end of defun)
31
+ let depth = 0;
32
+ for (const ch of stripped) {
33
+ if (ch === '(')
34
+ depth++;
35
+ else if (ch === ')')
36
+ depth--;
37
+ }
38
+ if (depth === 0 && defunText.trim().length > 0 && defunName) {
39
+ // End of defun - check if it uses command but no *error*
40
+ if (/\(command\b/.test(defunText) && !hasErrorHandler && !defunName.startsWith('c:')) {
41
+ issues.push({
42
+ file, line: defunStart, severity: 'warn', rule: 'error_handling',
43
+ message: (0, locale_1.t)('error_handling', defunName),
44
+ });
45
+ }
46
+ inDefun = false;
47
+ defunName = '';
48
+ }
49
+ }
50
+ }
51
+ return issues;
52
+ }
53
+ //# sourceMappingURL=error-handling.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-handling.js","sourceRoot":"","sources":["../../src/checks/error-handling.ts"],"names":[],"mappings":";;AAIA,gDAgDC;AAnDD,sCAA8B;AAC9B,oCAAqC;AAErC,SAAgB,kBAAkB,CAAC,OAAe,EAAE,IAAY;IAC9D,MAAM,MAAM,GAAY,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClC,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,IAAI,SAAS,GAAG,EAAE,CAAC;IACnB,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,SAAS,GAAG,EAAE,CAAC;IACnB,IAAI,eAAe,GAAG,KAAK,CAAC;IAE5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,QAAQ,GAAG,IAAA,iBAAS,EAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAErC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;YAC5C,IAAI,CAAC,EAAE,CAAC;gBACN,OAAO,GAAG,IAAI,CAAC;gBACf,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;gBACjB,UAAU,GAAG,CAAC,GAAG,CAAC,CAAC;gBACnB,SAAS,GAAG,EAAE,CAAC;gBACf,eAAe,GAAG,KAAK,CAAC;YAC1B,CAAC;QACH,CAAC;QAED,IAAI,OAAO,EAAE,CAAC;YACZ,SAAS,IAAI,QAAQ,GAAG,IAAI,CAAC;YAC7B,IAAI,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC;gBAAE,eAAe,GAAG,IAAI,CAAC;YAEzD,gDAAgD;YAChD,IAAI,KAAK,GAAG,CAAC,CAAC;YACd,KAAK,MAAM,EAAE,IAAI,QAAQ,EAAE,CAAC;gBAC1B,IAAI,EAAE,KAAK,GAAG;oBAAE,KAAK,EAAE,CAAC;qBACnB,IAAI,EAAE,KAAK,GAAG;oBAAE,KAAK,EAAE,CAAC;YAC/B,CAAC;YAED,IAAI,KAAK,KAAK,CAAC,IAAI,SAAS,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,IAAI,SAAS,EAAE,CAAC;gBAC5D,yDAAyD;gBACzD,IAAI,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,eAAe,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;oBACrF,MAAM,CAAC,IAAI,CAAC;wBACV,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB;wBAChE,OAAO,EAAE,IAAA,UAAC,EAAC,gBAAgB,EAAE,SAAS,CAAC;qBACxC,CAAC,CAAC;gBACL,CAAC;gBACD,OAAO,GAAG,KAAK,CAAC;gBAChB,SAAS,GAAG,EAAE,CAAC;YACjB,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Issue } from '../types';
2
+ export declare function checkExtraParens(content: string, file: string): Issue[];
3
+ //# sourceMappingURL=extra-parens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extra-parens.d.ts","sourceRoot":"","sources":["../../src/checks/extra-parens.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAIjC,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK,EAAE,CAoCvE"}
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkExtraParens = checkExtraParens;
4
+ const locale_1 = require("../locale");
5
+ const utils_1 = require("../utils");
6
+ function checkExtraParens(content, file) {
7
+ const issues = [];
8
+ const lines = content.split('\n');
9
+ let runningDepth = 0;
10
+ for (let i = 0; i < lines.length; i++) {
11
+ const stripped = (0, utils_1.stripLine)(lines[i]);
12
+ let closeOnly = stripped.trim();
13
+ // Empty line resets nothing; just continue tracking depth
14
+ if (!closeOnly)
15
+ continue;
16
+ // Count parens on this line
17
+ let lineOpen = 0, lineClose = 0;
18
+ for (const ch of stripped) {
19
+ if (ch === '(')
20
+ lineOpen++;
21
+ else if (ch === ')')
22
+ lineClose++;
23
+ }
24
+ // Check if this line is pure closing parens
25
+ if (/^\)+$/.test(closeOnly)) {
26
+ // Only flag if these closing parens exceed the running depth
27
+ // (i.e., they are unmatched / extra)
28
+ if (lineClose > runningDepth + lineOpen) {
29
+ const extra = lineClose - runningDepth - lineOpen;
30
+ issues.push({
31
+ file, line: i + 1, severity: 'warn', rule: 'extra_parens',
32
+ message: (0, locale_1.t)('extra_parens', extra),
33
+ });
34
+ }
35
+ }
36
+ runningDepth += lineOpen - lineClose;
37
+ if (runningDepth < 0)
38
+ runningDepth = 0;
39
+ }
40
+ return issues;
41
+ }
42
+ //# sourceMappingURL=extra-parens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extra-parens.js","sourceRoot":"","sources":["../../src/checks/extra-parens.ts"],"names":[],"mappings":";;AAIA,4CAoCC;AAvCD,sCAA8B;AAC9B,oCAAqC;AAErC,SAAgB,gBAAgB,CAAC,OAAe,EAAE,IAAY;IAC5D,MAAM,MAAM,GAAY,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClC,IAAI,YAAY,GAAG,CAAC,CAAC;IAErB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,QAAQ,GAAG,IAAA,iBAAS,EAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;QACpC,IAAI,SAAS,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAA;QAE/B,0DAA0D;QAC1D,IAAI,CAAC,SAAS;YAAE,SAAQ;QAExB,4BAA4B;QAC5B,IAAI,QAAQ,GAAG,CAAC,EAAE,SAAS,GAAG,CAAC,CAAA;QAC/B,KAAK,MAAM,EAAE,IAAI,QAAQ,EAAE,CAAC;YAC1B,IAAI,EAAE,KAAK,GAAG;gBAAE,QAAQ,EAAE,CAAA;iBACrB,IAAI,EAAE,KAAK,GAAG;gBAAE,SAAS,EAAE,CAAA;QAClC,CAAC;QAED,4CAA4C;QAC5C,IAAI,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;YAC5B,6DAA6D;YAC7D,qCAAqC;YACrC,IAAI,SAAS,GAAG,YAAY,GAAG,QAAQ,EAAE,CAAC;gBACxC,MAAM,KAAK,GAAG,SAAS,GAAG,YAAY,GAAG,QAAQ,CAAA;gBACjD,MAAM,CAAC,IAAI,CAAC;oBACV,IAAI,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc;oBACzD,OAAO,EAAE,IAAA,UAAC,EAAC,cAAc,EAAE,KAAK,CAAC;iBAClC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,YAAY,IAAI,QAAQ,GAAG,SAAS,CAAA;QACpC,IAAI,YAAY,GAAG,CAAC;YAAE,YAAY,GAAG,CAAC,CAAA;IACxC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Issue } from '../types';
2
+ export declare function checkFunctionComplexity(content: string, file: string, maxLines: number, maxNesting: number): Issue[];
3
+ //# sourceMappingURL=function-complexity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"function-complexity.d.ts","sourceRoot":"","sources":["../../src/checks/function-complexity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAIjC,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,KAAK,EAAE,CAmDpH"}