@atlisp/lint 0.1.3 → 0.1.4

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 (262) hide show
  1. package/README.md +5 -2
  2. package/atlisp-lint.default.json +29 -29
  3. package/bin/atlisp-lint +1 -1
  4. package/dist/checks/bare-names.js +4 -1
  5. package/dist/checks/cl-syntax.js +4 -1
  6. package/dist/checks/commented-code.d.ts +3 -0
  7. package/dist/checks/commented-code.js +46 -0
  8. package/dist/checks/constant-condition.d.ts +5 -0
  9. package/dist/checks/constant-condition.js +88 -0
  10. package/dist/checks/dangerous-calls.d.ts +2 -0
  11. package/dist/checks/dangerous-calls.js +70 -29
  12. package/dist/checks/dangling-defun.d.ts +6 -0
  13. package/dist/checks/dangling-defun.js +85 -0
  14. package/dist/checks/double-not.d.ts +5 -0
  15. package/dist/checks/double-not.js +30 -0
  16. package/dist/checks/empty-branch.d.ts +5 -0
  17. package/dist/checks/empty-branch.js +34 -0
  18. package/dist/checks/empty-comments.d.ts +3 -0
  19. package/dist/checks/empty-comments.js +26 -0
  20. package/dist/checks/encoding.js +13 -4
  21. package/dist/checks/function-complexity.d.ts +2 -0
  22. package/dist/checks/function-complexity.js +89 -45
  23. package/dist/checks/line-length.js +4 -1
  24. package/dist/checks/misplaced-else.d.ts +5 -0
  25. package/dist/checks/misplaced-else.js +31 -0
  26. package/dist/checks/missing-doc.js +6 -3
  27. package/dist/checks/missing-export.d.ts +13 -0
  28. package/dist/checks/missing-export.js +94 -0
  29. package/dist/checks/module-reg.js +9 -4
  30. package/dist/checks/multiple-setq.d.ts +5 -0
  31. package/dist/checks/multiple-setq.js +51 -0
  32. package/dist/checks/namespace-header.js +16 -6
  33. package/dist/checks/open-close.d.ts +2 -0
  34. package/dist/checks/open-close.js +18 -13
  35. package/dist/checks/parameter-naming.d.ts +2 -0
  36. package/dist/checks/parameter-naming.js +26 -14
  37. package/dist/checks/parens.js +8 -3
  38. package/dist/checks/quote-vs-function.d.ts +5 -0
  39. package/dist/checks/quote-vs-function.js +50 -0
  40. package/dist/checks/recursive-call.d.ts +5 -0
  41. package/dist/checks/recursive-call.js +49 -0
  42. package/dist/checks/redundant-cond.d.ts +5 -0
  43. package/dist/checks/redundant-cond.js +50 -0
  44. package/dist/checks/redundant-let.d.ts +5 -0
  45. package/dist/checks/redundant-let.js +31 -0
  46. package/dist/checks/redundant-nil-else.d.ts +5 -0
  47. package/dist/checks/redundant-nil-else.js +32 -0
  48. package/dist/checks/redundant-progn.d.ts +2 -0
  49. package/dist/checks/redundant-progn.js +18 -9
  50. package/dist/checks/redundant-quotes.d.ts +5 -0
  51. package/dist/checks/redundant-quotes.js +33 -0
  52. package/dist/checks/redundant-setq.d.ts +5 -0
  53. package/dist/checks/redundant-setq.js +34 -0
  54. package/dist/checks/self-compare.d.ts +5 -0
  55. package/dist/checks/self-compare.js +37 -0
  56. package/dist/checks/single-arg-and-or.d.ts +5 -0
  57. package/dist/checks/single-arg-and-or.js +32 -0
  58. package/dist/checks/token-in-url.js +4 -1
  59. package/dist/checks/trailing-paren.d.ts +3 -0
  60. package/dist/checks/trailing-paren.js +44 -0
  61. package/dist/checks/trailing-ws.js +4 -1
  62. package/dist/checks/unused-let.d.ts +5 -0
  63. package/dist/checks/unused-let.js +57 -0
  64. package/dist/checks/unused-local-fun.d.ts +5 -0
  65. package/dist/checks/unused-local-fun.js +62 -0
  66. package/dist/checks/unused-package-dep.d.ts +3 -0
  67. package/dist/checks/unused-package-dep.js +93 -0
  68. package/dist/checks/unused-param.d.ts +5 -0
  69. package/dist/checks/unused-param.js +63 -0
  70. package/dist/checks/unused-variable.d.ts +2 -0
  71. package/dist/checks/unused-variable.js +70 -42
  72. package/dist/checks/variable-shadow.d.ts +5 -0
  73. package/dist/checks/variable-shadow.js +66 -0
  74. package/dist/checks/vlax.js +8 -3
  75. package/dist/config.d.ts +1 -2
  76. package/dist/config.js +3 -35
  77. package/dist/disable.js +4 -1
  78. package/dist/formatters.d.ts +1 -2
  79. package/dist/formatters.js +8 -61
  80. package/dist/index.js +131 -201
  81. package/dist/locale.js +83 -91
  82. package/dist/project.d.ts +3 -0
  83. package/dist/project.js +138 -0
  84. package/dist/runner.d.ts +5 -11
  85. package/dist/runner.js +260 -71
  86. package/dist/sbcl.js +16 -11
  87. package/dist/worker.js +10 -5
  88. package/lib/lint-sbcl.lisp +19 -54
  89. package/package.json +11 -4
  90. package/LICENSE +0 -21
  91. package/dist/atlisp-lint.default.json +0 -90
  92. package/dist/cache.d.ts.map +0 -1
  93. package/dist/cache.js.map +0 -1
  94. package/dist/checks/append-single.d.ts +0 -3
  95. package/dist/checks/append-single.d.ts.map +0 -1
  96. package/dist/checks/append-single.js +0 -17
  97. package/dist/checks/append-single.js.map +0 -1
  98. package/dist/checks/arg-count.d.ts +0 -3
  99. package/dist/checks/arg-count.d.ts.map +0 -1
  100. package/dist/checks/arg-count.js +0 -120
  101. package/dist/checks/arg-count.js.map +0 -1
  102. package/dist/checks/bare-names.d.ts.map +0 -1
  103. package/dist/checks/bare-names.js.map +0 -1
  104. package/dist/checks/cl-syntax.d.ts.map +0 -1
  105. package/dist/checks/cl-syntax.js.map +0 -1
  106. package/dist/checks/comment-style.d.ts +0 -3
  107. package/dist/checks/comment-style.d.ts.map +0 -1
  108. package/dist/checks/comment-style.js +0 -21
  109. package/dist/checks/comment-style.js.map +0 -1
  110. package/dist/checks/cond-simplify.d.ts +0 -3
  111. package/dist/checks/cond-simplify.d.ts.map +0 -1
  112. package/dist/checks/cond-simplify.js +0 -42
  113. package/dist/checks/cond-simplify.js.map +0 -1
  114. package/dist/checks/dangerous-calls.d.ts.map +0 -1
  115. package/dist/checks/dangerous-calls.js.map +0 -1
  116. package/dist/checks/dynamic-doc.d.ts +0 -3
  117. package/dist/checks/dynamic-doc.d.ts.map +0 -1
  118. package/dist/checks/dynamic-doc.js +0 -21
  119. package/dist/checks/dynamic-doc.js.map +0 -1
  120. package/dist/checks/empty-catch.d.ts +0 -3
  121. package/dist/checks/empty-catch.d.ts.map +0 -1
  122. package/dist/checks/empty-catch.js +0 -31
  123. package/dist/checks/empty-catch.js.map +0 -1
  124. package/dist/checks/encoding.d.ts.map +0 -1
  125. package/dist/checks/encoding.js.map +0 -1
  126. package/dist/checks/eq-usage.d.ts +0 -3
  127. package/dist/checks/eq-usage.d.ts.map +0 -1
  128. package/dist/checks/eq-usage.js +0 -22
  129. package/dist/checks/eq-usage.js.map +0 -1
  130. package/dist/checks/error-handling.d.ts +0 -3
  131. package/dist/checks/error-handling.d.ts.map +0 -1
  132. package/dist/checks/error-handling.js +0 -53
  133. package/dist/checks/error-handling.js.map +0 -1
  134. package/dist/checks/extra-parens.d.ts +0 -3
  135. package/dist/checks/extra-parens.d.ts.map +0 -1
  136. package/dist/checks/extra-parens.js +0 -42
  137. package/dist/checks/extra-parens.js.map +0 -1
  138. package/dist/checks/function-complexity.d.ts.map +0 -1
  139. package/dist/checks/function-complexity.js.map +0 -1
  140. package/dist/checks/function-order.d.ts +0 -3
  141. package/dist/checks/function-order.d.ts.map +0 -1
  142. package/dist/checks/function-order.js +0 -33
  143. package/dist/checks/function-order.js.map +0 -1
  144. package/dist/checks/global-naming.d.ts +0 -3
  145. package/dist/checks/global-naming.d.ts.map +0 -1
  146. package/dist/checks/global-naming.js +0 -51
  147. package/dist/checks/global-naming.js.map +0 -1
  148. package/dist/checks/index.d.ts +0 -3
  149. package/dist/checks/index.d.ts.map +0 -1
  150. package/dist/checks/index.js +0 -108
  151. package/dist/checks/index.js.map +0 -1
  152. package/dist/checks/lambda-syntax.d.ts +0 -3
  153. package/dist/checks/lambda-syntax.d.ts.map +0 -1
  154. package/dist/checks/lambda-syntax.js +0 -22
  155. package/dist/checks/lambda-syntax.js.map +0 -1
  156. package/dist/checks/line-length.d.ts.map +0 -1
  157. package/dist/checks/line-length.js.map +0 -1
  158. package/dist/checks/long-function-call.d.ts +0 -3
  159. package/dist/checks/long-function-call.d.ts.map +0 -1
  160. package/dist/checks/long-function-call.js +0 -48
  161. package/dist/checks/long-function-call.js.map +0 -1
  162. package/dist/checks/loop-optimization.d.ts +0 -3
  163. package/dist/checks/loop-optimization.d.ts.map +0 -1
  164. package/dist/checks/loop-optimization.js +0 -17
  165. package/dist/checks/loop-optimization.js.map +0 -1
  166. package/dist/checks/magic-number.d.ts +0 -3
  167. package/dist/checks/magic-number.d.ts.map +0 -1
  168. package/dist/checks/magic-number.js +0 -21
  169. package/dist/checks/magic-number.js.map +0 -1
  170. package/dist/checks/missing-doc.d.ts.map +0 -1
  171. package/dist/checks/missing-doc.js.map +0 -1
  172. package/dist/checks/mixed-indent.d.ts +0 -3
  173. package/dist/checks/mixed-indent.d.ts.map +0 -1
  174. package/dist/checks/mixed-indent.js +0 -19
  175. package/dist/checks/mixed-indent.js.map +0 -1
  176. package/dist/checks/module-reg.d.ts.map +0 -1
  177. package/dist/checks/module-reg.js.map +0 -1
  178. package/dist/checks/namespace-header.d.ts.map +0 -1
  179. package/dist/checks/namespace-header.js.map +0 -1
  180. package/dist/checks/no-return.d.ts +0 -3
  181. package/dist/checks/no-return.d.ts.map +0 -1
  182. package/dist/checks/no-return.js +0 -45
  183. package/dist/checks/no-return.js.map +0 -1
  184. package/dist/checks/nth-usage.d.ts +0 -3
  185. package/dist/checks/nth-usage.d.ts.map +0 -1
  186. package/dist/checks/nth-usage.js +0 -17
  187. package/dist/checks/nth-usage.js.map +0 -1
  188. package/dist/checks/open-close.d.ts.map +0 -1
  189. package/dist/checks/open-close.js.map +0 -1
  190. package/dist/checks/parameter-naming.d.ts.map +0 -1
  191. package/dist/checks/parameter-naming.js.map +0 -1
  192. package/dist/checks/parens.d.ts.map +0 -1
  193. package/dist/checks/parens.js.map +0 -1
  194. package/dist/checks/quote-style.d.ts +0 -3
  195. package/dist/checks/quote-style.d.ts.map +0 -1
  196. package/dist/checks/quote-style.js +0 -22
  197. package/dist/checks/quote-style.js.map +0 -1
  198. package/dist/checks/redundant-if.d.ts +0 -3
  199. package/dist/checks/redundant-if.d.ts.map +0 -1
  200. package/dist/checks/redundant-if.js +0 -17
  201. package/dist/checks/redundant-if.js.map +0 -1
  202. package/dist/checks/redundant-progn.d.ts.map +0 -1
  203. package/dist/checks/redundant-progn.js.map +0 -1
  204. package/dist/checks/setq-multiple.d.ts +0 -3
  205. package/dist/checks/setq-multiple.d.ts.map +0 -1
  206. package/dist/checks/setq-multiple.js +0 -17
  207. package/dist/checks/setq-multiple.js.map +0 -1
  208. package/dist/checks/shadow-builtin.d.ts +0 -3
  209. package/dist/checks/shadow-builtin.d.ts.map +0 -1
  210. package/dist/checks/shadow-builtin.js +0 -29
  211. package/dist/checks/shadow-builtin.js.map +0 -1
  212. package/dist/checks/strcat-usage.d.ts +0 -3
  213. package/dist/checks/strcat-usage.d.ts.map +0 -1
  214. package/dist/checks/strcat-usage.js +0 -22
  215. package/dist/checks/strcat-usage.js.map +0 -1
  216. package/dist/checks/token-in-url.d.ts.map +0 -1
  217. package/dist/checks/token-in-url.js.map +0 -1
  218. package/dist/checks/trailing-ws.d.ts.map +0 -1
  219. package/dist/checks/trailing-ws.js.map +0 -1
  220. package/dist/checks/type-check.d.ts +0 -3
  221. package/dist/checks/type-check.d.ts.map +0 -1
  222. package/dist/checks/type-check.js +0 -26
  223. package/dist/checks/type-check.js.map +0 -1
  224. package/dist/checks/unused-variable.d.ts.map +0 -1
  225. package/dist/checks/unused-variable.js.map +0 -1
  226. package/dist/checks/vlax.d.ts.map +0 -1
  227. package/dist/checks/vlax.js.map +0 -1
  228. package/dist/config.d.ts.map +0 -1
  229. package/dist/config.js.map +0 -1
  230. package/dist/disable.d.ts.map +0 -1
  231. package/dist/disable.js.map +0 -1
  232. package/dist/formatters.d.ts.map +0 -1
  233. package/dist/formatters.js.map +0 -1
  234. package/dist/index.d.ts.map +0 -1
  235. package/dist/index.js.map +0 -1
  236. package/dist/lib/lint-sbcl.lisp +0 -161
  237. package/dist/locale.d.ts.map +0 -1
  238. package/dist/locale.js.map +0 -1
  239. package/dist/rules.d.ts +0 -9
  240. package/dist/rules.d.ts.map +0 -1
  241. package/dist/rules.js +0 -58
  242. package/dist/rules.js.map +0 -1
  243. package/dist/runner.d.ts.map +0 -1
  244. package/dist/runner.js.map +0 -1
  245. package/dist/sbcl.d.ts.map +0 -1
  246. package/dist/sbcl.js.map +0 -1
  247. package/dist/stub-packages.json +0 -41
  248. package/dist/types.d.ts.map +0 -1
  249. package/dist/types.js.map +0 -1
  250. package/dist/utils.d.ts.map +0 -1
  251. package/dist/utils.js.map +0 -1
  252. package/dist/validate.d.ts +0 -8
  253. package/dist/validate.d.ts.map +0 -1
  254. package/dist/validate.js +0 -59
  255. package/dist/validate.js.map +0 -1
  256. package/dist/watch.d.ts +0 -9
  257. package/dist/watch.d.ts.map +0 -1
  258. package/dist/watch.js +0 -109
  259. package/dist/watch.js.map +0 -1
  260. package/dist/worker.d.ts.map +0 -1
  261. package/dist/worker.js.map +0 -1
  262. package/pre-commit/hook.sh +0 -4
package/dist/locale.js CHANGED
@@ -9,54 +9,55 @@ const messages = {
9
9
  'encoding.bom': 'UTF-8 BOM detected',
10
10
  'encoding.non_utf8_cad': 'Non-UTF-8 encoding (may cause CAD bracket matching errors)',
11
11
  'encoding.non_utf8': 'Non-UTF-8 encoding detected',
12
- 'cl_syntax': "Common Lisp syntax '{0}' (not valid in AutoLISP)",
12
+ cl_syntax: "Common Lisp syntax '{0}' (not valid in AutoLISP)",
13
13
  'dangerous.quit': 'quit call (terminates CAD process)',
14
14
  'dangerous.exit': 'exit call (terminates CAD process)',
15
15
  'dangerous.command_shell': 'command shell call (shell injection risk)',
16
16
  'dangerous.startapp': 'startapp call (launches external process)',
17
17
  'dangerous.vl_registry_write': 'vl-registry-write call (modifies Windows registry)',
18
- 'vlax_without_loading': 'vlax-* call without vl-load-com in file',
19
- 'token_in_url': 'Possible token exposure in string: token= in URL',
20
- 'open_without_close': 'File has {0} open() calls but {1} close() calls (possible resource leak)',
21
- 'bare_function_names': "Unnamespaced function '{0}' (missing @:: or C: prefix)",
22
- 'module_registration': 'Module file missing @::*modules* registration (expected in last lines)',
18
+ vlax_without_loading: 'vlax-* call without vl-load-com in file',
19
+ token_in_url: 'Possible token exposure in string: token= in URL',
20
+ open_without_close: 'File has {0} open() calls but {1} close() calls (possible resource leak)',
21
+ bare_function_names: "Unnamespaced function '{0}' (missing @:: or C: prefix)",
22
+ module_registration: 'Module file missing @::*modules* registration (expected in last lines)',
23
23
  'namespace_header.missing': 'Missing (in-package {0}) header',
24
24
  'namespace_header.wrong': 'in-package target is not {0}',
25
- 'trailing_whitespace': 'Trailing whitespace',
26
- 'line_length': 'Line length {0} exceeds {1} characters',
25
+ trailing_whitespace: 'Trailing whitespace',
26
+ line_length: 'Line length {0} exceeds {1} characters',
27
27
  'function_complexity.lines': "Function '{0}' has {1} lines (max {2})",
28
28
  'function_complexity.nesting': "Function '{0}' nesting depth {1} exceeds {2}",
29
- 'parameter_naming': "Parameter '{0}' in '{1}' starts with uppercase (AutoLISP convention: lowercase)",
30
- 'unused_variable': "Variable '{0}' is set but never used",
31
- 'missing_doc': "Function '{0}' is missing a documentation comment",
32
- 'error_handling': "Function '{0}' uses command but has no *error* handler",
33
- 'global_naming': "Global variable '{0}' should be wrapped in *...*",
34
- 'extra_parens': "Suspicious closing parens: {0} ')' on a single line",
35
- 'arg_count': "Call to '{0}' has {1} argument(s) but definition expects {2}",
36
- 'strcat_usage': "Use strcat instead of + for string concatenation",
37
- 'cond_simplify': "Single-branch cond can be simplified to if",
38
- 'redundant_progn': "Redundant progn in branch (if/when/cond already has implicit progn)",
39
- 'quote_style': "Use ' instead of (quote ...)",
40
- 'eq_usage': "Use = for numeric comparison instead of eq",
41
- 'lambda_syntax': "Use #' instead of (function (lambda ...))",
42
- 'comment_style': "Comment should start with ; followed by a space",
43
- 'empty_catch': "vl-catch-all-apply result not checked with vl-catch-all-error-p",
44
- 'nth_usage': 'Use car instead of (nth 0 ...)',
45
- 'append_single': 'Use cons instead of (append (list ...))',
46
- 'setq_multiple': 'Combine multiple setq into one (setq a 1 b 2)',
47
- 'function_order': "Function '{0}' defined after its first use",
48
- 'magic_number': 'Magic number {0} should be a named constant',
49
- 'mixed_indent': 'Mixed tabs and spaces in indentation',
50
- 'long_function_call': 'Function call has {0} arguments, consider splitting across lines',
51
- 'no_return': "Function '{0}' has no return value",
52
- 'shadow_builtin': "Function '{0}' shadows a built-in AutoLISP function",
53
- 'dynamic_doc': "Command '{0}' may be missing trailing (princ) for clean exit",
54
- 'loop_optimization': 'Consider using foreach with a lambda instead of while/assoc loop',
55
- 'type_check': "Variable '{0}' from getvar should be type-checked before use",
56
- 'redundant_if': "Redundant progn in if/when/unless branch",
29
+ parameter_naming: "Parameter '{0}' in '{1}' starts with uppercase (AutoLISP convention: lowercase)",
30
+ unused_variable: "Variable '{0}' is set but never used",
31
+ missing_doc: "Function '{0}' is missing a documentation comment",
32
+ unused_parameter: "Parameter '{0}' in '{1}' is never used",
33
+ constant_condition: "Constant condition '{0}' in {1} possibly leftover debug code",
34
+ redundant_progn: 'Redundant progn in {0}: only one form inside',
35
+ empty_branch: "Empty branch in '{0}' no body forms",
36
+ unused_let_binding: "Let binding '{0}' is never used",
37
+ recursive_call: "Function '{0}' calls itself possible infinite recursion",
38
+ variable_shadow: "Variable '{0}' is set with setq inside a let that binds the same name",
39
+ 'redundant_cond.single': 'Single-clause {0} simplify to (if ...)',
40
+ 'redundant_cond.t_last': '{0} with T as last clause condition — use (if ...) else branch instead',
41
+ unused_local_fun: "Local function/variable '{0}' is defined in defun with / but never used",
42
+ multiple_setq: 'Consecutive (setq ...) forms consider merging into a single (setq ...)',
43
+ redundant_quotes: "Redundant double quote ''x can be simplified to 'x",
44
+ trailing_paren: "Excess closing parenthesis: {0} extra ')' found",
45
+ empty_comment: 'Empty comment line contains only a semicolon with no text',
46
+ redundant_setq: "Redundant setq: variable '{0}' is set to itself",
47
+ redundant_nil_else: 'Redundant nil else branch (if cond x nil) can be (if cond x)',
48
+ single_arg_and_or: 'Single-argument {0} simplifies to just the argument',
49
+ redundant_let: 'let with no bindings use (progn ...) instead',
50
+ self_compare: 'Self-comparison {0} is always T or always nil',
51
+ misplaced_else: '(if (not {0}) ...) — swap branches for better readability: (if {0} ... ... reversed)',
52
+ quote_vs_function: 'Quoted lambda passed to {0} use (function (lambda ...)) instead for compiled code',
53
+ commented_code: 'Commented-out code detected remove or uncomment if needed',
54
+ double_not: 'Double (not (not ...)) simplifies to single not',
55
+ dangling_defun: "Function '{0}' is defined but never called",
56
+ missing_export: "Function '{0}' is not registered in @::*modules*",
57
+ unused_package_dep: "Imported package '{0}' is never referenced",
57
58
  'runner.read_error': 'Cannot read file',
58
59
  'sbcl.script_not_found': 'lint-sbcl.lisp not found at {0}',
59
- 'sbcl.not_found': "SBCL (Steel Bank Common Lisp) is required but not found.\nInstall it from: https://www.sbcl.org/platform-table.html\nOr on Windows via: winget install sbcl\nOr on macOS via: brew install sbcl\nOr on Linux via: apt install sbcl",
60
+ 'sbcl.not_found': 'SBCL (Steel Bank Common Lisp) is required but not found.\nInstall it from: https://www.sbcl.org/platform-table.html\nOr on Windows via: winget install sbcl\nOr on macOS via: brew install sbcl\nOr on Linux via: apt install sbcl',
60
61
  'summary.tag_fail': 'FAIL',
61
62
  'summary.tag_warn': 'WARN',
62
63
  'summary.line': 'Line',
@@ -65,72 +66,69 @@ const messages = {
65
66
  'summary.errors_warnings': ' {0} error(s), {1} warning(s)',
66
67
  'summary.done': '=== Done ===',
67
68
  'index.no_files': 'No .lsp files found',
68
- 'index.config_exists': '.atlisp-lint.json already exists',
69
+ 'index.config_exists': 'atlisp-lint.json already exists',
69
70
  'index.config_created': 'Created {0}',
70
71
  'index.not_git': 'Not a git repository: no .git/hooks directory',
71
72
  'index.hook_installed': 'Installed pre-commit hook at {0}',
72
73
  'index.fixed': 'Auto-fixed: {0}',
73
- 'index.watching': 'Watching for changes',
74
- 'index.watch_hint': 'Press Ctrl+C to stop',
75
- 'index.watch_status': 'Checked {0} files, {1} errors, {2} warnings',
76
- 'index.config_valid': 'Configuration is valid',
74
+ 'index.cached': 'Cached, skipping',
75
+ 'index.all_cached': 'All files are cached, nothing to lint',
77
76
  'index.cache_cleared': 'Cache cleared',
78
- 'index.progress': 'Progress: {0}/{1} ({2}%)',
79
- 'index.max_warnings': 'Max warnings exceeded',
80
77
  },
81
78
  zh: {
82
79
  'parens.mismatch': "括号不匹配:{0} 个 '(' vs {1} 个 ')'({2})",
83
80
  'encoding.bom': '检测到 UTF-8 BOM',
84
81
  'encoding.non_utf8_cad': '非 UTF-8 编码(可能导致 CAD 括号匹配错误)',
85
82
  'encoding.non_utf8': '检测到非 UTF-8 编码',
86
- 'cl_syntax': "Common Lisp 语法 '{0}'(在 AutoLISP 中无效)",
83
+ cl_syntax: "Common Lisp 语法 '{0}'(在 AutoLISP 中无效)",
87
84
  'dangerous.quit': 'quit 调用(会终止 CAD 进程)',
88
85
  'dangerous.exit': 'exit 调用(会终止 CAD 进程)',
89
86
  'dangerous.command_shell': 'command shell 调用(存在命令注入风险)',
90
87
  'dangerous.startapp': 'startapp 调用(会启动外部程序)',
91
88
  'dangerous.vl_registry_write': 'vl-registry-write 调用(会修改 Windows 注册表)',
92
- 'vlax_without_loading': '文件中使用了 vlax-* 函数但未调用 vl-load-com',
93
- 'token_in_url': '字符串中可能泄露令牌:URL 中包含 token=',
94
- 'open_without_close': '文件中有 {0} 个 open() 调用,但只有 {1} 个 close() 调用(可能存在资源泄露)',
95
- 'bare_function_names': "函数 '{0}' 缺少命名空间前缀(缺少 @:: 或 C: 前缀)",
96
- 'module_registration': '模块文件缺少 @::*modules* 注册(应在文件末尾附近)',
89
+ vlax_without_loading: '文件中使用了 vlax-* 函数但未调用 vl-load-com',
90
+ token_in_url: '字符串中可能泄露令牌:URL 中包含 token=',
91
+ open_without_close: '文件中有 {0} 个 open() 调用,但只有 {1} 个 close() 调用(可能存在资源泄露)',
92
+ bare_function_names: "函数 '{0}' 缺少命名空间前缀(缺少 @:: 或 C: 前缀)",
93
+ module_registration: '模块文件缺少 @::*modules* 注册(应在文件末尾附近)',
97
94
  'namespace_header.missing': '缺少 (in-package {0}) 头',
98
95
  'namespace_header.wrong': 'in-package 目标不是 {0}',
99
- 'trailing_whitespace': '行尾有多余空格',
100
- 'line_length': '行长度 {0} 超过 {1} 个字符',
96
+ trailing_whitespace: '行尾有多余空格',
97
+ line_length: '行长度 {0} 超过 {1} 个字符',
101
98
  'function_complexity.lines': "函数 '{0}' 有 {1} 行(最大 {2} 行)",
102
99
  'function_complexity.nesting': "函数 '{0}' 嵌套深度 {1} 超过 {2}",
103
- 'parameter_naming': "参数 '{0}' 在 '{1}' 中首字母大写(AutoLISP 惯例:小写)",
104
- 'unused_variable': "变量 '{0}' 被赋值但从未使用",
105
- 'missing_doc': "函数 '{0}' 缺少注释说明",
106
- 'error_handling': "函数 '{0}' 使用了 command 但没有 *error* 错误处理",
107
- 'global_naming': "全局变量 '{0}' 应使用 *...* 包裹",
108
- 'extra_parens': "可疑的连续右括号:单行出现 {0} ')'",
109
- 'arg_count': "调用 '{0}' 有 {1} 个参数,但定义需要 {2} 个",
110
- 'strcat_usage': "字符串拼接应使用 strcat 而非 +",
111
- 'cond_simplify': "单分支 cond 可以简化为 if",
112
- 'redundant_progn': "分支中存在多余的 progn(if/when/cond 已隐含 progn)",
113
- 'quote_style': "使用 ' 代替 (quote ...)",
114
- 'eq_usage': "数字比较应使用 = 而非 eq",
115
- 'lambda_syntax': "使用 #' 代替 (function (lambda ...))",
116
- 'comment_style': "注释应在 ; 后加一个空格",
117
- 'empty_catch': "vl-catch-all-apply 的结果未用 vl-catch-all-error-p 检查",
118
- 'nth_usage': "使用 car 代替 (nth 0 ...)",
119
- 'append_single': "使用 cons 代替 (append (list ...))",
120
- 'setq_multiple': "多个 setq 可以合并为一个 (setq a 1 b 2)",
121
- 'function_order': "函数 '{0}' 定义在使用之后",
122
- 'magic_number': "魔法数字 {0} 应定义为命名常量",
123
- 'mixed_indent': "缩进中混用了 tab 和空格",
124
- 'long_function_call': "函数调用有 {0} 个参数,建议换行",
125
- 'no_return': "函数 '{0}' 没有返回值",
126
- 'shadow_builtin': "函数 '{0}' 覆盖了 AutoLISP 内置函数",
127
- 'dynamic_doc': "命令 '{0}' 可能缺少尾部的 (princ) 以实现干净退出",
128
- 'loop_optimization': '建议使用 foreach + lambda 替代 while/assoc 循环',
129
- 'type_check': "变量 '{0}' 来自 getvar,使用前应做类型检查",
130
- 'redundant_if': 'if/when/unless 分支中存在冗余的 progn',
100
+ parameter_naming: "参数 '{0}' 在 '{1}' 中首字母大写(AutoLISP 惯例:小写)",
101
+ unused_variable: "变量 '{0}' 被赋值但从未使用",
102
+ missing_doc: "函数 '{0}' 缺少注释说明",
103
+ unused_parameter: "参数 '{0}' 在函数 '{1}' 中从未使用",
104
+ constant_condition: "常量条件 '{0}' {1} 中——可能是调试残留代码",
105
+ redundant_progn: '冗余 progn:{0} 内只有一个表达式',
106
+ empty_branch: "'{0}' 的条件分支为空——没有表达式",
107
+ unused_let_binding: "let 绑定 '{0}' 从未被使用",
108
+ recursive_call: "函数 '{0}' 调用了自身——可能存在无限递归",
109
+ variable_shadow: "变量 '{0}' let 绑定了相同名称后被 setq 赋值",
110
+ 'redundant_cond.single': '单子句 {0} ——建议简化为 (if ...)',
111
+ 'redundant_cond.t_last': '{0} 的最后一条子句条件为 T ——建议改用 (if ...) else 分支',
112
+ unused_local_fun: "局部函数/变量 '{0}' defun / 后定义但从未使用",
113
+ multiple_setq: '连续多个 (setq ...) ——建议合并为一个 (setq ...)',
114
+ redundant_quotes: "冗余双引号 —— ''x 可以简化为 'x",
115
+ trailing_paren: "多余闭合括号:发现 {0} 个额外的 ')'",
116
+ empty_comment: '空注释行 —— 分号后没有内容',
117
+ redundant_setq: "冗余 setq:变量 '{0}' 赋值为自身",
118
+ redundant_nil_else: '冗余 nil 分支 —— (if cond x nil) 可简化为 (if cond x)',
119
+ single_arg_and_or: '单参数 {0} —— 可直接简化为该参数本身',
120
+ redundant_let: '无绑定的 let —— 建议改用 (progn ...)',
121
+ self_compare: '自比较 {0} 的结果恒为 T 或恒为 nil',
122
+ misplaced_else: '(if (not {0}) ...) —— 建议交换分支以提高可读性: (if {0} ... ... 交换后)',
123
+ quote_vs_function: '在 {0} 中使用引用 lambda —— 建议改用 (function (lambda ...)) 以支持编译优化',
124
+ commented_code: '检测到被注释掉的代码 —— 请删除或取消注释',
125
+ double_not: '双重 (not (not ...)) —— 可以简化为单个 not',
126
+ dangling_defun: "函数 '{0}' 定义了但从未被调用",
127
+ missing_export: "函数 '{0}' 未注册到 @::*modules*",
128
+ unused_package_dep: "导入的包 '{0}' 从未被引用",
131
129
  'runner.read_error': '无法读取文件',
132
130
  'sbcl.script_not_found': '未找到 lint-sbcl.lisp:{0}',
133
- 'sbcl.not_found': "未找到 SBCL(Steel Bank Common Lisp)。\n请从以下地址安装:https://www.sbcl.org/platform-table.html\nWindows 下可用:winget install sbcl\nmacOS 下可用:brew install sbcl\nLinux 下可用:apt install sbcl",
131
+ 'sbcl.not_found': '未找到 SBCL(Steel Bank Common Lisp)。\n请从以下地址安装:https://www.sbcl.org/platform-table.html\nWindows 下可用:winget install sbcl\nmacOS 下可用:brew install sbcl\nLinux 下可用:apt install sbcl',
134
132
  'summary.tag_fail': '失败',
135
133
  'summary.tag_warn': '警告',
136
134
  'summary.line': '行',
@@ -139,18 +137,14 @@ const messages = {
139
137
  'summary.errors_warnings': ' {0} 个错误,{1} 个警告',
140
138
  'summary.done': '=== 完成 ===',
141
139
  'index.no_files': '未找到 .lsp 文件',
142
- 'index.config_exists': '.atlisp-lint.json 已存在',
140
+ 'index.config_exists': 'atlisp-lint.json 已存在',
143
141
  'index.config_created': '已创建 {0}',
144
142
  'index.not_git': '不是 git 仓库:没有 .git/hooks 目录',
145
143
  'index.hook_installed': '已在 {0} 安装 pre-commit hook',
146
144
  'index.fixed': '自动修复:{0}',
147
- 'index.watching': '正在监听文件变化',
148
- 'index.watch_hint': '按 Ctrl+C 停止',
149
- 'index.watch_status': '检查了 {0} 个文件,{1} 个错误,{2} 个警告',
150
- 'index.config_valid': '配置文件校验通过',
145
+ 'index.cached': '已缓存,跳过',
146
+ 'index.all_cached': '所有文件均已缓存,无需检查',
151
147
  'index.cache_cleared': '缓存已清除',
152
- 'index.progress': '进度:{0}/{1}({2}%)',
153
- 'index.max_warnings': '超出最大警告数',
154
148
  },
155
149
  };
156
150
  let currentLocale = 'zh';
@@ -161,9 +155,7 @@ function getLocale() {
161
155
  return currentLocale;
162
156
  }
163
157
  function t(key, ...args) {
164
- const msg = messages[currentLocale]?.[key] ||
165
- messages['en']?.[key] ||
166
- key;
158
+ const msg = messages[currentLocale]?.[key] || messages['en']?.[key] || key;
167
159
  return msg.replace(/\{(\d+)\}/g, (_, index) => String(args[Number(index)] ?? ''));
168
160
  }
169
161
  //# sourceMappingURL=locale.js.map
@@ -0,0 +1,3 @@
1
+ import { Issue, LintConfig } from './types';
2
+ export declare function lintProject(files: string[], config: LintConfig, rootDir: string): Issue[];
3
+ //# sourceMappingURL=project.d.ts.map
@@ -0,0 +1,138 @@
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.lintProject = lintProject;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const parser_1 = require("@atlisp/parser");
40
+ const dangling_defun_1 = require("./checks/dangling-defun");
41
+ const missing_export_1 = require("./checks/missing-export");
42
+ const unused_package_dep_1 = require("./checks/unused-package-dep");
43
+ const locale_1 = require("./locale");
44
+ function collectDefuns(file) {
45
+ const content = fs.readFileSync(file, 'utf-8');
46
+ const ast = (0, parser_1.parseAst)(content);
47
+ const results = [];
48
+ const defunNodes = (0, parser_1.astFindAll)(ast, (n) => (0, parser_1.astIsList)(n, 'defun') || (0, parser_1.astIsList)(n, 'defun-q'));
49
+ for (const node of defunNodes) {
50
+ if (node.children && node.children.length >= 2 && (0, parser_1.astIsSymbol)(node.children[1])) {
51
+ results.push({ name: node.children[1].name, line: node.pos.line });
52
+ }
53
+ }
54
+ return results;
55
+ }
56
+ function lintProject(files, config, rootDir) {
57
+ (0, locale_1.setLocale)(config.locale || 'zh');
58
+ const allIssues = [];
59
+ const defuns = { defuns: new Map() };
60
+ const fileContents = new Map();
61
+ for (const filepath of files) {
62
+ try {
63
+ const content = fs.readFileSync(filepath, 'utf-8');
64
+ fileContents.set(filepath, content);
65
+ }
66
+ catch {
67
+ continue;
68
+ }
69
+ }
70
+ for (const [filepath] of fileContents) {
71
+ const defunList = collectDefuns(filepath);
72
+ for (const d of defunList) {
73
+ const list = defuns.defuns.get(d.name) || [];
74
+ list.push({ file: filepath, line: d.line });
75
+ defuns.defuns.set(d.name, list);
76
+ }
77
+ }
78
+ for (const [filepath] of fileContents) {
79
+ const relPath = path.relative(rootDir, filepath);
80
+ const override = findProjectOverride(filepath);
81
+ const checks = override?.checks || config.checks;
82
+ if (checks['dangling_defun'] !== 'off') {
83
+ const danglingIssues = (0, dangling_defun_1.checkDanglingDefun)(filepath, defuns.defuns);
84
+ for (const iss of danglingIssues) {
85
+ iss.file = relPath;
86
+ allIssues.push(iss);
87
+ }
88
+ }
89
+ if (checks['missing_export'] !== 'off') {
90
+ const pkgDir = findPackageDir(filepath);
91
+ if (pkgDir) {
92
+ const missingIssues = (0, missing_export_1.checkMissingExport)(filepath, pkgDir, defuns.defuns);
93
+ for (const iss of missingIssues) {
94
+ iss.file = relPath;
95
+ allIssues.push(iss);
96
+ }
97
+ }
98
+ }
99
+ if (checks['unused_package_dep'] !== 'off') {
100
+ const depIssues = (0, unused_package_dep_1.checkUnusedPackageDep)(filepath);
101
+ for (const iss of depIssues) {
102
+ iss.file = relPath;
103
+ allIssues.push(iss);
104
+ }
105
+ }
106
+ }
107
+ return allIssues;
108
+ }
109
+ function findProjectOverride(filepath) {
110
+ let dir = path.dirname(filepath);
111
+ for (;;) {
112
+ const cfgPath = path.join(dir, '.atlisp-lint.json');
113
+ if (fs.existsSync(cfgPath)) {
114
+ try {
115
+ return JSON.parse(fs.readFileSync(cfgPath, 'utf-8'));
116
+ }
117
+ catch {
118
+ return null;
119
+ }
120
+ }
121
+ const parent = path.dirname(dir);
122
+ if (parent === dir)
123
+ return null;
124
+ dir = parent;
125
+ }
126
+ }
127
+ function findPackageDir(filepath) {
128
+ let dir = path.dirname(filepath);
129
+ for (;;) {
130
+ if (fs.existsSync(path.join(dir, 'pkg.lsp')))
131
+ return dir;
132
+ const parent = path.dirname(dir);
133
+ if (parent === dir)
134
+ return null;
135
+ dir = parent;
136
+ }
137
+ }
138
+ //# sourceMappingURL=project.js.map
package/dist/runner.d.ts CHANGED
@@ -1,14 +1,8 @@
1
1
  import { Issue, LintConfig } from './types';
2
- export declare function parseIgnoreFile(rootDir: string): RegExp[];
3
- export declare function lintFiles(files: string[], config: LintConfig, rootDir: string, options?: {
4
- useCache?: boolean;
5
- ignorePatterns?: RegExp[];
6
- onProgress?: (done: number, total: number) => void;
7
- }): Issue[];
8
- export declare function lintFilesParallel(files: string[], config: LintConfig, rootDir: string, options?: {
9
- ignorePatterns?: RegExp[];
10
- onProgress?: (done: number, total: number) => void;
11
- }): Promise<Issue[]>;
2
+ export declare function runChecks(content: string, file: string, config: LintConfig): Issue[];
3
+ /** Single-pass visitor-based runChecks using AstVisitor */
4
+ export declare function runChecksWithVisitor(content: string, file: string, config: LintConfig): Issue[];
5
+ export declare function lintFiles(files: string[], config: LintConfig, rootDir: string): Issue[];
6
+ export declare function lintFilesParallel(files: string[], config: LintConfig, rootDir: string): Promise<Issue[]>;
12
7
  export declare function fixFile(filepath: string): string[];
13
- export declare function clearCache(rootDir: string): void;
14
8
  //# sourceMappingURL=runner.d.ts.map