@atlisp/lint 0.1.3 → 0.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 (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
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkRecursiveCall = checkRecursiveCall;
4
+ exports.checkRecursiveCallAst = checkRecursiveCallAst;
5
+ const locale_1 = require("../locale");
6
+ const parser_1 = require("@atlisp/parser");
7
+ function checkRecursiveCall(content, file) {
8
+ const ast = (0, parser_1.parseAst)(content);
9
+ return checkRecursiveCallAst(ast, file);
10
+ }
11
+ function checkRecursiveCallAst(ast, file) {
12
+ const issues = [];
13
+ const defuns = (0, parser_1.astFindAll)(ast, (n) => (0, parser_1.astIsList)(n, 'defun'));
14
+ for (const defun of defuns) {
15
+ if (!defun.children || defun.children.length < 3)
16
+ continue;
17
+ const nameNode = defun.children[1];
18
+ const funcName = nameNode.type === 'symbol' && nameNode.name ? nameNode.name : '';
19
+ if (!funcName)
20
+ continue;
21
+ // Walk the function body (skip name and param list)
22
+ for (let i = 3; i < defun.children.length; i++) {
23
+ if (hasSelfCall(defun.children[i], funcName)) {
24
+ issues.push({
25
+ file,
26
+ line: defun.pos.line,
27
+ severity: 'warn',
28
+ rule: 'recursive_call',
29
+ message: (0, locale_1.t)('recursive_call', funcName),
30
+ });
31
+ break; // one issue per function
32
+ }
33
+ }
34
+ }
35
+ return issues;
36
+ }
37
+ function hasSelfCall(node, funcName) {
38
+ for (const n of (0, parser_1.astWalk)(node)) {
39
+ // Check if this node is a list whose car is the function name
40
+ if (n.type === 'list' && n.children && n.children.length > 0) {
41
+ const car = n.children[0];
42
+ if (car.type === 'symbol' && car.name === funcName) {
43
+ return true;
44
+ }
45
+ }
46
+ }
47
+ return false;
48
+ }
49
+ //# sourceMappingURL=recursive-call.js.map
@@ -0,0 +1,5 @@
1
+ import { Issue } from '../types';
2
+ import { AstNode } from '@atlisp/parser';
3
+ export declare function checkRedundantCond(content: string, file: string): Issue[];
4
+ export declare function checkRedundantCondAst(ast: AstNode, file: string): Issue[];
5
+ //# sourceMappingURL=redundant-cond.d.ts.map
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkRedundantCond = checkRedundantCond;
4
+ exports.checkRedundantCondAst = checkRedundantCondAst;
5
+ const locale_1 = require("../locale");
6
+ const parser_1 = require("@atlisp/parser");
7
+ function checkRedundantCond(content, file) {
8
+ const ast = (0, parser_1.parseAst)(content);
9
+ return checkRedundantCondAst(ast, file);
10
+ }
11
+ function checkRedundantCondAst(ast, file) {
12
+ const issues = [];
13
+ const condNodes = (0, parser_1.astFindListWithHead)(ast, 'cond');
14
+ for (const node of condNodes) {
15
+ if (!node.children)
16
+ continue;
17
+ const clauses = node.children.slice(1); // skip 'cond' itself
18
+ // Single clause cond: (cond (test body)) → (if test body)
19
+ if (clauses.length === 1) {
20
+ const clause = clauses[0];
21
+ if (clause.type === 'list' && clause.children && clause.children.length >= 2) {
22
+ issues.push({
23
+ file,
24
+ line: node.pos.line,
25
+ severity: 'warn',
26
+ rule: 'redundant_cond',
27
+ message: (0, locale_1.t)('redundant_cond.single', 'cond'),
28
+ });
29
+ }
30
+ }
31
+ // Two-clause cond with T/t as last condition: (cond (x y) (T z)) → (if x y z)
32
+ if (clauses.length === 2) {
33
+ const last = clauses[clauses.length - 1];
34
+ if (last.type === 'list' && last.children && last.children.length > 0) {
35
+ const condTest = last.children[0];
36
+ if (condTest.type === 'symbol' && (condTest.name === 'T' || condTest.name === 't')) {
37
+ issues.push({
38
+ file,
39
+ line: condTest.pos.line,
40
+ severity: 'warn',
41
+ rule: 'redundant_cond',
42
+ message: (0, locale_1.t)('redundant_cond.t_last', 'cond'),
43
+ });
44
+ }
45
+ }
46
+ }
47
+ }
48
+ return issues;
49
+ }
50
+ //# sourceMappingURL=redundant-cond.js.map
@@ -0,0 +1,5 @@
1
+ import { Issue } from '../types';
2
+ import { AstNode } from '@atlisp/parser';
3
+ export declare function checkRedundantLet(content: string, file: string): Issue[];
4
+ export declare function checkRedundantLetAst(ast: AstNode, file: string): Issue[];
5
+ //# sourceMappingURL=redundant-let.d.ts.map
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkRedundantLet = checkRedundantLet;
4
+ exports.checkRedundantLetAst = checkRedundantLetAst;
5
+ const locale_1 = require("../locale");
6
+ const parser_1 = require("@atlisp/parser");
7
+ function checkRedundantLet(content, file) {
8
+ const ast = (0, parser_1.parseAst)(content);
9
+ return checkRedundantLetAst(ast, file);
10
+ }
11
+ function checkRedundantLetAst(ast, file) {
12
+ const issues = [];
13
+ const letNodes = (0, parser_1.astFindAll)(ast, (n) => (0, parser_1.astIsList)(n, 'let'));
14
+ for (const node of letNodes) {
15
+ if (!node.children || node.children.length < 2)
16
+ continue;
17
+ const bindings = node.children[1];
18
+ // (let () ...) — binding list exists but is empty
19
+ if (bindings.type === 'list' && (!bindings.children || bindings.children.length === 0)) {
20
+ issues.push({
21
+ file,
22
+ line: node.pos.line,
23
+ severity: 'warn',
24
+ rule: 'redundant_let',
25
+ message: (0, locale_1.t)('redundant_let'),
26
+ });
27
+ }
28
+ }
29
+ return issues;
30
+ }
31
+ //# sourceMappingURL=redundant-let.js.map
@@ -0,0 +1,5 @@
1
+ import { Issue } from '../types';
2
+ import { AstNode } from '@atlisp/parser';
3
+ export declare function checkRedundantNilElse(content: string, file: string): Issue[];
4
+ export declare function checkRedundantNilElseAst(ast: AstNode, file: string): Issue[];
5
+ //# sourceMappingURL=redundant-nil-else.d.ts.map
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkRedundantNilElse = checkRedundantNilElse;
4
+ exports.checkRedundantNilElseAst = checkRedundantNilElseAst;
5
+ const locale_1 = require("../locale");
6
+ const parser_1 = require("@atlisp/parser");
7
+ function checkRedundantNilElse(content, file) {
8
+ const ast = (0, parser_1.parseAst)(content);
9
+ return checkRedundantNilElseAst(ast, file);
10
+ }
11
+ function checkRedundantNilElseAst(ast, file) {
12
+ const issues = [];
13
+ // Find (if cond then nil) — else branch is nil which is the default
14
+ const ifNodes = (0, parser_1.astFindAll)(ast, (n) => (0, parser_1.astIsList)(n, 'if'));
15
+ for (const node of ifNodes) {
16
+ if (!node.children || node.children.length !== 4)
17
+ continue;
18
+ // (if cond then nil) — 4 children: if, cond, then, nil-else
19
+ const elseBranch = node.children[3];
20
+ if (elseBranch.type === 'symbol' && elseBranch.name === 'nil') {
21
+ issues.push({
22
+ file,
23
+ line: elseBranch.pos.line,
24
+ severity: 'warn',
25
+ rule: 'redundant_nil_else',
26
+ message: (0, locale_1.t)('redundant_nil_else'),
27
+ });
28
+ }
29
+ }
30
+ return issues;
31
+ }
32
+ //# sourceMappingURL=redundant-nil-else.js.map
@@ -1,3 +1,5 @@
1
1
  import { Issue } from '../types';
2
+ import { AstNode } from '@atlisp/parser';
2
3
  export declare function checkRedundantProgn(content: string, file: string): Issue[];
4
+ export declare function checkRedundantPrognAst(ast: AstNode, file: string): Issue[];
3
5
  //# sourceMappingURL=redundant-progn.d.ts.map
@@ -1,19 +1,28 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.checkRedundantProgn = checkRedundantProgn;
4
+ exports.checkRedundantPrognAst = checkRedundantPrognAst;
4
5
  const locale_1 = require("../locale");
5
- const utils_1 = require("../utils");
6
+ const parser_1 = require("@atlisp/parser");
6
7
  function checkRedundantProgn(content, file) {
8
+ const ast = (0, parser_1.parseAst)(content);
9
+ return checkRedundantPrognAst(ast, file);
10
+ }
11
+ function checkRedundantPrognAst(ast, file) {
7
12
  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]).trim();
11
- // Detect (if expr (progn ...) ...) or (cond ((t) (progn ...)))
12
- const m = stripped.match(/\((if|when|unless|cond)\s+.+\(progn\b/);
13
- if (m) {
13
+ const prognNodes = (0, parser_1.astFindAll)(ast, (n) => (0, parser_1.astIsList)(n, 'progn'));
14
+ for (const node of prognNodes) {
15
+ if (!node.children)
16
+ continue;
17
+ // count forms after 'progn'
18
+ const bodyCount = node.children.length - 1;
19
+ if (bodyCount === 1) {
14
20
  issues.push({
15
- file, line: i + 1, severity: 'warn', rule: 'redundant_progn',
16
- message: (0, locale_1.t)('redundant_progn'),
21
+ file,
22
+ line: node.pos.line,
23
+ severity: 'warn',
24
+ rule: 'redundant_progn',
25
+ message: (0, locale_1.t)('redundant_progn', '(progn ...)'),
17
26
  });
18
27
  }
19
28
  }
@@ -0,0 +1,5 @@
1
+ import { Issue } from '../types';
2
+ import { AstNode } from '@atlisp/parser';
3
+ export declare function checkRedundantQuotes(content: string, file: string): Issue[];
4
+ export declare function checkRedundantQuotesAst(ast: AstNode, file: string): Issue[];
5
+ //# sourceMappingURL=redundant-quotes.d.ts.map
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkRedundantQuotes = checkRedundantQuotes;
4
+ exports.checkRedundantQuotesAst = checkRedundantQuotesAst;
5
+ const locale_1 = require("../locale");
6
+ const parser_1 = require("@atlisp/parser");
7
+ function checkRedundantQuotes(content, file) {
8
+ const ast = (0, parser_1.parseAst)(content);
9
+ return checkRedundantQuotesAst(ast, file);
10
+ }
11
+ function checkRedundantQuotesAst(ast, file) {
12
+ const issues = [];
13
+ // ''x → (quote (quote x)) — nested quote
14
+ const doubleQuotes = (0, parser_1.astFindAll)(ast, (n) => {
15
+ if (!(0, parser_1.astIsList)(n, 'quote'))
16
+ return false;
17
+ if (!n.children || n.children.length < 2)
18
+ return false;
19
+ return (0, parser_1.astIsList)(n.children[1], 'quote');
20
+ });
21
+ for (const node of doubleQuotes) {
22
+ issues.push({
23
+ file,
24
+ line: node.pos.line,
25
+ severity: 'warn',
26
+ rule: 'redundant_quotes',
27
+ message: (0, locale_1.t)('redundant_quotes'),
28
+ });
29
+ }
30
+ // '(quote x) → (quote (quote x)) — same representation via AST
31
+ return issues;
32
+ }
33
+ //# sourceMappingURL=redundant-quotes.js.map
@@ -0,0 +1,5 @@
1
+ import { Issue } from '../types';
2
+ import { AstNode } from '@atlisp/parser';
3
+ export declare function checkRedundantSetq(content: string, file: string): Issue[];
4
+ export declare function checkRedundantSetqAst(ast: AstNode, file: string): Issue[];
5
+ //# sourceMappingURL=redundant-setq.d.ts.map
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkRedundantSetq = checkRedundantSetq;
4
+ exports.checkRedundantSetqAst = checkRedundantSetqAst;
5
+ const locale_1 = require("../locale");
6
+ const parser_1 = require("@atlisp/parser");
7
+ function checkRedundantSetq(content, file) {
8
+ const ast = (0, parser_1.parseAst)(content);
9
+ return checkRedundantSetqAst(ast, file);
10
+ }
11
+ function checkRedundantSetqAst(ast, file) {
12
+ const issues = [];
13
+ const setqNodes = (0, parser_1.astFindAll)(ast, (n) => (0, parser_1.astIsList)(n, 'setq'));
14
+ for (const node of setqNodes) {
15
+ if (!node.children)
16
+ continue;
17
+ // (setq x x) — variable is set to itself
18
+ for (let i = 1; i < node.children.length - 1; i += 2) {
19
+ const varNode = node.children[i];
20
+ const valNode = node.children[i + 1];
21
+ if (varNode.type === 'symbol' && valNode.type === 'symbol' && varNode.name === valNode.name && varNode.name) {
22
+ issues.push({
23
+ file,
24
+ line: varNode.pos.line,
25
+ severity: 'warn',
26
+ rule: 'redundant_setq',
27
+ message: (0, locale_1.t)('redundant_setq', varNode.name),
28
+ });
29
+ }
30
+ }
31
+ }
32
+ return issues;
33
+ }
34
+ //# sourceMappingURL=redundant-setq.js.map
@@ -0,0 +1,5 @@
1
+ import { Issue } from '../types';
2
+ import { AstNode } from '@atlisp/parser';
3
+ export declare function checkSelfCompare(content: string, file: string): Issue[];
4
+ export declare function checkSelfCompareAst(ast: AstNode, file: string): Issue[];
5
+ //# sourceMappingURL=self-compare.d.ts.map
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkSelfCompare = checkSelfCompare;
4
+ exports.checkSelfCompareAst = checkSelfCompareAst;
5
+ const locale_1 = require("../locale");
6
+ const parser_1 = require("@atlisp/parser");
7
+ const COMPARE_FUNCTIONS = new Set(['=', '/=', '<', '>', '<=', '>=', 'eq', 'equal']);
8
+ function checkSelfCompare(content, file) {
9
+ const ast = (0, parser_1.parseAst)(content);
10
+ return checkSelfCompareAst(ast, file);
11
+ }
12
+ function checkSelfCompareAst(ast, file) {
13
+ const issues = [];
14
+ for (const fn of COMPARE_FUNCTIONS) {
15
+ const nodes = (0, parser_1.astFindAll)(ast, (n) => (0, parser_1.astIsList)(n, fn));
16
+ for (const node of nodes) {
17
+ if (!node.children)
18
+ continue;
19
+ // (= x x) — 3 children: '=', x, x
20
+ if (node.children.length === 3) {
21
+ const a = node.children[1];
22
+ const b = node.children[2];
23
+ if (a.type === 'symbol' && b.type === 'symbol' && a.name === b.name && a.name) {
24
+ issues.push({
25
+ file,
26
+ line: node.pos.line,
27
+ severity: 'warn',
28
+ rule: 'self_compare',
29
+ message: (0, locale_1.t)('self_compare', `(${fn} ${a.name} ${a.name})`),
30
+ });
31
+ }
32
+ }
33
+ }
34
+ }
35
+ return issues;
36
+ }
37
+ //# sourceMappingURL=self-compare.js.map
@@ -0,0 +1,5 @@
1
+ import { Issue } from '../types';
2
+ import { AstNode } from '@atlisp/parser';
3
+ export declare function checkSingleArgAndOr(content: string, file: string): Issue[];
4
+ export declare function checkSingleArgAndOrAst(ast: AstNode, file: string): Issue[];
5
+ //# sourceMappingURL=single-arg-and-or.d.ts.map
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkSingleArgAndOr = checkSingleArgAndOr;
4
+ exports.checkSingleArgAndOrAst = checkSingleArgAndOrAst;
5
+ const locale_1 = require("../locale");
6
+ const parser_1 = require("@atlisp/parser");
7
+ function checkSingleArgAndOr(content, file) {
8
+ const ast = (0, parser_1.parseAst)(content);
9
+ return checkSingleArgAndOrAst(ast, file);
10
+ }
11
+ function checkSingleArgAndOrAst(ast, file) {
12
+ const issues = [];
13
+ for (const form of ['and', 'or']) {
14
+ const nodes = (0, parser_1.astFindAll)(ast, (n) => (0, parser_1.astIsList)(n, form));
15
+ for (const node of nodes) {
16
+ if (!node.children)
17
+ continue;
18
+ // (and x) — 2 children: 'and', x
19
+ if (node.children.length === 2) {
20
+ issues.push({
21
+ file,
22
+ line: node.pos.line,
23
+ severity: 'warn',
24
+ rule: 'single_arg_and_or',
25
+ message: (0, locale_1.t)('single_arg_and_or', `(${form} ...)`),
26
+ });
27
+ }
28
+ }
29
+ }
30
+ return issues;
31
+ }
32
+ //# sourceMappingURL=single-arg-and-or.js.map
@@ -11,7 +11,10 @@ function checkTokenInUrl(content, file) {
11
11
  for (const s of strings) {
12
12
  if (/token=/i.test(s)) {
13
13
  issues.push({
14
- file, line: i + 1, severity: 'warn', rule: 'token_in_url',
14
+ file,
15
+ line: i + 1,
16
+ severity: 'warn',
17
+ rule: 'token_in_url',
15
18
  message: (0, locale_1.t)('token_in_url'),
16
19
  });
17
20
  break; // one per line
@@ -0,0 +1,3 @@
1
+ import { Issue } from '../types';
2
+ export declare function checkTrailingParen(content: string, file: string): Issue[];
3
+ //# sourceMappingURL=trailing-paren.d.ts.map
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkTrailingParen = checkTrailingParen;
4
+ const locale_1 = require("../locale");
5
+ function checkTrailingParen(content, file) {
6
+ // Count total parens to detect excess closing parens
7
+ let openCount = 0;
8
+ let closeCount = 0;
9
+ let inStr = false;
10
+ // We must parse strings accurately to avoid counting parens inside strings
11
+ for (let i = 0; i < content.length; i++) {
12
+ const ch = content[i];
13
+ if (ch === '"')
14
+ inStr = !inStr;
15
+ if (inStr) {
16
+ if (ch === '\\')
17
+ i++; // skip escaped char
18
+ continue;
19
+ }
20
+ if (ch === ';') {
21
+ // skip to end of line
22
+ while (i < content.length && content[i] !== '\n')
23
+ i++;
24
+ continue;
25
+ }
26
+ if (ch === '(')
27
+ openCount++;
28
+ else if (ch === ')')
29
+ closeCount++;
30
+ }
31
+ if (closeCount > openCount) {
32
+ return [
33
+ {
34
+ file,
35
+ line: 1,
36
+ severity: 'warn',
37
+ rule: 'trailing_paren',
38
+ message: (0, locale_1.t)('trailing_paren', closeCount - openCount),
39
+ },
40
+ ];
41
+ }
42
+ return [];
43
+ }
44
+ //# sourceMappingURL=trailing-paren.js.map
@@ -9,7 +9,10 @@ function checkTrailingWhitespace(content, file) {
9
9
  const line = lines[i];
10
10
  if (line.length > 0 && /[ \t]$/.test(line)) {
11
11
  issues.push({
12
- file, line: i + 1, severity: 'warn', rule: 'trailing_whitespace',
12
+ file,
13
+ line: i + 1,
14
+ severity: 'warn',
15
+ rule: 'trailing_whitespace',
13
16
  message: (0, locale_1.t)('trailing_whitespace'),
14
17
  });
15
18
  }
@@ -0,0 +1,5 @@
1
+ import { Issue } from '../types';
2
+ import { AstNode } from '@atlisp/parser';
3
+ export declare function checkUnusedLetBinding(content: string, file: string): Issue[];
4
+ export declare function checkUnusedLetBindingAst(ast: AstNode, file: string): Issue[];
5
+ //# sourceMappingURL=unused-let.d.ts.map
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkUnusedLetBinding = checkUnusedLetBinding;
4
+ exports.checkUnusedLetBindingAst = checkUnusedLetBindingAst;
5
+ const locale_1 = require("../locale");
6
+ const parser_1 = require("@atlisp/parser");
7
+ function checkUnusedLetBinding(content, file) {
8
+ const ast = (0, parser_1.parseAst)(content);
9
+ return checkUnusedLetBindingAst(ast, file);
10
+ }
11
+ function checkUnusedLetBindingAst(ast, file) {
12
+ const issues = [];
13
+ const letNodes = (0, parser_1.astFindAll)(ast, (n) => (0, parser_1.astIsList)(n, 'let'));
14
+ for (const node of letNodes) {
15
+ if (!node.children || node.children.length < 2)
16
+ continue;
17
+ const bindingList = node.children[1];
18
+ if (bindingList.type !== 'list' || !bindingList.children)
19
+ continue;
20
+ // Collect let-bound variables
21
+ const bindings = [];
22
+ for (const binding of bindingList.children) {
23
+ if (binding.type !== 'list' || !binding.children || binding.children.length === 0)
24
+ continue;
25
+ const varNode = binding.children[0];
26
+ if (varNode.type !== 'symbol' || !varNode.name)
27
+ continue;
28
+ if (varNode.name === 'T' || varNode.name === 'nil')
29
+ continue;
30
+ bindings.push({ name: varNode.name, node: varNode });
31
+ }
32
+ if (bindings.length === 0)
33
+ continue;
34
+ // Collect symbol references in the body (forms after the binding list)
35
+ const bodyRefs = new Set();
36
+ for (let i = 2; i < node.children.length; i++) {
37
+ for (const n of (0, parser_1.astWalk)(node.children[i])) {
38
+ if (n.type === 'symbol' && n.name) {
39
+ bodyRefs.add(n.name);
40
+ }
41
+ }
42
+ }
43
+ for (const { name, node: varNode } of bindings) {
44
+ if (!bodyRefs.has(name)) {
45
+ issues.push({
46
+ file,
47
+ line: varNode.pos.line,
48
+ severity: 'warn',
49
+ rule: 'unused_let_binding',
50
+ message: (0, locale_1.t)('unused_let_binding', name),
51
+ });
52
+ }
53
+ }
54
+ }
55
+ return issues;
56
+ }
57
+ //# sourceMappingURL=unused-let.js.map
@@ -0,0 +1,5 @@
1
+ import { Issue } from '../types';
2
+ import { AstNode } from '@atlisp/parser';
3
+ export declare function checkUnusedLocalFun(content: string, file: string): Issue[];
4
+ export declare function checkUnusedLocalFunAst(ast: AstNode, file: string): Issue[];
5
+ //# sourceMappingURL=unused-local-fun.d.ts.map
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkUnusedLocalFun = checkUnusedLocalFun;
4
+ exports.checkUnusedLocalFunAst = checkUnusedLocalFunAst;
5
+ const locale_1 = require("../locale");
6
+ const parser_1 = require("@atlisp/parser");
7
+ function checkUnusedLocalFun(content, file) {
8
+ const ast = (0, parser_1.parseAst)(content);
9
+ return checkUnusedLocalFunAst(ast, file);
10
+ }
11
+ function checkUnusedLocalFunAst(ast, file) {
12
+ const issues = [];
13
+ const defuns = (0, parser_1.astFindListWithHead)(ast, 'defun');
14
+ for (const defun of defuns) {
15
+ if (!defun.children || defun.children.length < 3)
16
+ continue;
17
+ const paramList = defun.children[2];
18
+ if (paramList.type !== 'list' || !paramList.children)
19
+ continue;
20
+ // Collect local variables after `/` in param list
21
+ // (defun foo (x / y z) ...) → y, z are local vars
22
+ const locals = [];
23
+ let afterSlash = false;
24
+ for (const p of paramList.children) {
25
+ if (p.type === 'symbol' && p.name === '/') {
26
+ afterSlash = true;
27
+ continue;
28
+ }
29
+ if (!afterSlash)
30
+ continue;
31
+ if (p.type !== 'symbol' || !p.name)
32
+ continue;
33
+ if (p.name === 'T' || p.name === 'nil')
34
+ continue;
35
+ locals.push({ name: p.name, node: p });
36
+ }
37
+ if (locals.length === 0)
38
+ continue;
39
+ // Collect symbol references in the body (forms after param list, skip params)
40
+ const bodyRefs = new Set();
41
+ for (let i = 3; i < defun.children.length; i++) {
42
+ for (const n of (0, parser_1.astWalk)(defun.children[i])) {
43
+ if (n.type === 'symbol' && n.name) {
44
+ bodyRefs.add(n.name);
45
+ }
46
+ }
47
+ }
48
+ for (const { name, node } of locals) {
49
+ if (!bodyRefs.has(name)) {
50
+ issues.push({
51
+ file,
52
+ line: node.pos.line,
53
+ severity: 'warn',
54
+ rule: 'unused_local_fun',
55
+ message: (0, locale_1.t)('unused_local_fun', name),
56
+ });
57
+ }
58
+ }
59
+ }
60
+ return issues;
61
+ }
62
+ //# sourceMappingURL=unused-local-fun.js.map
@@ -0,0 +1,3 @@
1
+ import { Issue } from '../types';
2
+ export declare function checkUnusedPackageDep(file: string): Issue[];
3
+ //# sourceMappingURL=unused-package-dep.d.ts.map