@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.
- package/README.md +5 -2
- package/atlisp-lint.default.json +29 -29
- package/bin/atlisp-lint +1 -1
- package/dist/checks/bare-names.js +4 -1
- package/dist/checks/cl-syntax.js +4 -1
- package/dist/checks/commented-code.d.ts +3 -0
- package/dist/checks/commented-code.js +46 -0
- package/dist/checks/constant-condition.d.ts +5 -0
- package/dist/checks/constant-condition.js +88 -0
- package/dist/checks/dangerous-calls.d.ts +2 -0
- package/dist/checks/dangerous-calls.js +70 -29
- package/dist/checks/dangling-defun.d.ts +6 -0
- package/dist/checks/dangling-defun.js +85 -0
- package/dist/checks/double-not.d.ts +5 -0
- package/dist/checks/double-not.js +30 -0
- package/dist/checks/empty-branch.d.ts +5 -0
- package/dist/checks/empty-branch.js +34 -0
- package/dist/checks/empty-comments.d.ts +3 -0
- package/dist/checks/empty-comments.js +26 -0
- package/dist/checks/encoding.js +13 -4
- package/dist/checks/function-complexity.d.ts +2 -0
- package/dist/checks/function-complexity.js +89 -45
- package/dist/checks/line-length.js +4 -1
- package/dist/checks/misplaced-else.d.ts +5 -0
- package/dist/checks/misplaced-else.js +31 -0
- package/dist/checks/missing-doc.js +6 -3
- package/dist/checks/missing-export.d.ts +13 -0
- package/dist/checks/missing-export.js +94 -0
- package/dist/checks/module-reg.js +9 -4
- package/dist/checks/multiple-setq.d.ts +5 -0
- package/dist/checks/multiple-setq.js +51 -0
- package/dist/checks/namespace-header.js +16 -6
- package/dist/checks/open-close.d.ts +2 -0
- package/dist/checks/open-close.js +18 -13
- package/dist/checks/parameter-naming.d.ts +2 -0
- package/dist/checks/parameter-naming.js +26 -14
- package/dist/checks/parens.js +8 -3
- package/dist/checks/quote-vs-function.d.ts +5 -0
- package/dist/checks/quote-vs-function.js +50 -0
- package/dist/checks/recursive-call.d.ts +5 -0
- package/dist/checks/recursive-call.js +49 -0
- package/dist/checks/redundant-cond.d.ts +5 -0
- package/dist/checks/redundant-cond.js +50 -0
- package/dist/checks/redundant-let.d.ts +5 -0
- package/dist/checks/redundant-let.js +31 -0
- package/dist/checks/redundant-nil-else.d.ts +5 -0
- package/dist/checks/redundant-nil-else.js +32 -0
- package/dist/checks/redundant-progn.d.ts +2 -0
- package/dist/checks/redundant-progn.js +18 -9
- package/dist/checks/redundant-quotes.d.ts +5 -0
- package/dist/checks/redundant-quotes.js +33 -0
- package/dist/checks/redundant-setq.d.ts +5 -0
- package/dist/checks/redundant-setq.js +34 -0
- package/dist/checks/self-compare.d.ts +5 -0
- package/dist/checks/self-compare.js +37 -0
- package/dist/checks/single-arg-and-or.d.ts +5 -0
- package/dist/checks/single-arg-and-or.js +32 -0
- package/dist/checks/token-in-url.js +4 -1
- package/dist/checks/trailing-paren.d.ts +3 -0
- package/dist/checks/trailing-paren.js +44 -0
- package/dist/checks/trailing-ws.js +4 -1
- package/dist/checks/unused-let.d.ts +5 -0
- package/dist/checks/unused-let.js +57 -0
- package/dist/checks/unused-local-fun.d.ts +5 -0
- package/dist/checks/unused-local-fun.js +62 -0
- package/dist/checks/unused-package-dep.d.ts +3 -0
- package/dist/checks/unused-package-dep.js +93 -0
- package/dist/checks/unused-param.d.ts +5 -0
- package/dist/checks/unused-param.js +63 -0
- package/dist/checks/unused-variable.d.ts +2 -0
- package/dist/checks/unused-variable.js +70 -42
- package/dist/checks/variable-shadow.d.ts +5 -0
- package/dist/checks/variable-shadow.js +66 -0
- package/dist/checks/vlax.js +8 -3
- package/dist/config.d.ts +1 -2
- package/dist/config.js +3 -35
- package/dist/disable.js +4 -1
- package/dist/formatters.d.ts +1 -2
- package/dist/formatters.js +8 -61
- package/dist/index.js +131 -201
- package/dist/locale.js +83 -91
- package/dist/project.d.ts +3 -0
- package/dist/project.js +138 -0
- package/dist/runner.d.ts +5 -11
- package/dist/runner.js +260 -71
- package/dist/sbcl.js +16 -11
- package/dist/worker.js +10 -5
- package/lib/lint-sbcl.lisp +19 -54
- package/package.json +11 -4
- package/LICENSE +0 -21
- package/dist/atlisp-lint.default.json +0 -90
- package/dist/cache.d.ts.map +0 -1
- package/dist/cache.js.map +0 -1
- package/dist/checks/append-single.d.ts +0 -3
- package/dist/checks/append-single.d.ts.map +0 -1
- package/dist/checks/append-single.js +0 -17
- package/dist/checks/append-single.js.map +0 -1
- package/dist/checks/arg-count.d.ts +0 -3
- package/dist/checks/arg-count.d.ts.map +0 -1
- package/dist/checks/arg-count.js +0 -120
- package/dist/checks/arg-count.js.map +0 -1
- package/dist/checks/bare-names.d.ts.map +0 -1
- package/dist/checks/bare-names.js.map +0 -1
- package/dist/checks/cl-syntax.d.ts.map +0 -1
- package/dist/checks/cl-syntax.js.map +0 -1
- package/dist/checks/comment-style.d.ts +0 -3
- package/dist/checks/comment-style.d.ts.map +0 -1
- package/dist/checks/comment-style.js +0 -21
- package/dist/checks/comment-style.js.map +0 -1
- package/dist/checks/cond-simplify.d.ts +0 -3
- package/dist/checks/cond-simplify.d.ts.map +0 -1
- package/dist/checks/cond-simplify.js +0 -42
- package/dist/checks/cond-simplify.js.map +0 -1
- package/dist/checks/dangerous-calls.d.ts.map +0 -1
- package/dist/checks/dangerous-calls.js.map +0 -1
- package/dist/checks/dynamic-doc.d.ts +0 -3
- package/dist/checks/dynamic-doc.d.ts.map +0 -1
- package/dist/checks/dynamic-doc.js +0 -21
- package/dist/checks/dynamic-doc.js.map +0 -1
- package/dist/checks/empty-catch.d.ts +0 -3
- package/dist/checks/empty-catch.d.ts.map +0 -1
- package/dist/checks/empty-catch.js +0 -31
- package/dist/checks/empty-catch.js.map +0 -1
- package/dist/checks/encoding.d.ts.map +0 -1
- package/dist/checks/encoding.js.map +0 -1
- package/dist/checks/eq-usage.d.ts +0 -3
- package/dist/checks/eq-usage.d.ts.map +0 -1
- package/dist/checks/eq-usage.js +0 -22
- package/dist/checks/eq-usage.js.map +0 -1
- package/dist/checks/error-handling.d.ts +0 -3
- package/dist/checks/error-handling.d.ts.map +0 -1
- package/dist/checks/error-handling.js +0 -53
- package/dist/checks/error-handling.js.map +0 -1
- package/dist/checks/extra-parens.d.ts +0 -3
- package/dist/checks/extra-parens.d.ts.map +0 -1
- package/dist/checks/extra-parens.js +0 -42
- package/dist/checks/extra-parens.js.map +0 -1
- package/dist/checks/function-complexity.d.ts.map +0 -1
- package/dist/checks/function-complexity.js.map +0 -1
- package/dist/checks/function-order.d.ts +0 -3
- package/dist/checks/function-order.d.ts.map +0 -1
- package/dist/checks/function-order.js +0 -33
- package/dist/checks/function-order.js.map +0 -1
- package/dist/checks/global-naming.d.ts +0 -3
- package/dist/checks/global-naming.d.ts.map +0 -1
- package/dist/checks/global-naming.js +0 -51
- package/dist/checks/global-naming.js.map +0 -1
- package/dist/checks/index.d.ts +0 -3
- package/dist/checks/index.d.ts.map +0 -1
- package/dist/checks/index.js +0 -108
- package/dist/checks/index.js.map +0 -1
- package/dist/checks/lambda-syntax.d.ts +0 -3
- package/dist/checks/lambda-syntax.d.ts.map +0 -1
- package/dist/checks/lambda-syntax.js +0 -22
- package/dist/checks/lambda-syntax.js.map +0 -1
- package/dist/checks/line-length.d.ts.map +0 -1
- package/dist/checks/line-length.js.map +0 -1
- package/dist/checks/long-function-call.d.ts +0 -3
- package/dist/checks/long-function-call.d.ts.map +0 -1
- package/dist/checks/long-function-call.js +0 -48
- package/dist/checks/long-function-call.js.map +0 -1
- package/dist/checks/loop-optimization.d.ts +0 -3
- package/dist/checks/loop-optimization.d.ts.map +0 -1
- package/dist/checks/loop-optimization.js +0 -17
- package/dist/checks/loop-optimization.js.map +0 -1
- package/dist/checks/magic-number.d.ts +0 -3
- package/dist/checks/magic-number.d.ts.map +0 -1
- package/dist/checks/magic-number.js +0 -21
- package/dist/checks/magic-number.js.map +0 -1
- package/dist/checks/missing-doc.d.ts.map +0 -1
- package/dist/checks/missing-doc.js.map +0 -1
- package/dist/checks/mixed-indent.d.ts +0 -3
- package/dist/checks/mixed-indent.d.ts.map +0 -1
- package/dist/checks/mixed-indent.js +0 -19
- package/dist/checks/mixed-indent.js.map +0 -1
- package/dist/checks/module-reg.d.ts.map +0 -1
- package/dist/checks/module-reg.js.map +0 -1
- package/dist/checks/namespace-header.d.ts.map +0 -1
- package/dist/checks/namespace-header.js.map +0 -1
- package/dist/checks/no-return.d.ts +0 -3
- package/dist/checks/no-return.d.ts.map +0 -1
- package/dist/checks/no-return.js +0 -45
- package/dist/checks/no-return.js.map +0 -1
- package/dist/checks/nth-usage.d.ts +0 -3
- package/dist/checks/nth-usage.d.ts.map +0 -1
- package/dist/checks/nth-usage.js +0 -17
- package/dist/checks/nth-usage.js.map +0 -1
- package/dist/checks/open-close.d.ts.map +0 -1
- package/dist/checks/open-close.js.map +0 -1
- package/dist/checks/parameter-naming.d.ts.map +0 -1
- package/dist/checks/parameter-naming.js.map +0 -1
- package/dist/checks/parens.d.ts.map +0 -1
- package/dist/checks/parens.js.map +0 -1
- package/dist/checks/quote-style.d.ts +0 -3
- package/dist/checks/quote-style.d.ts.map +0 -1
- package/dist/checks/quote-style.js +0 -22
- package/dist/checks/quote-style.js.map +0 -1
- package/dist/checks/redundant-if.d.ts +0 -3
- package/dist/checks/redundant-if.d.ts.map +0 -1
- package/dist/checks/redundant-if.js +0 -17
- package/dist/checks/redundant-if.js.map +0 -1
- package/dist/checks/redundant-progn.d.ts.map +0 -1
- package/dist/checks/redundant-progn.js.map +0 -1
- package/dist/checks/setq-multiple.d.ts +0 -3
- package/dist/checks/setq-multiple.d.ts.map +0 -1
- package/dist/checks/setq-multiple.js +0 -17
- package/dist/checks/setq-multiple.js.map +0 -1
- package/dist/checks/shadow-builtin.d.ts +0 -3
- package/dist/checks/shadow-builtin.d.ts.map +0 -1
- package/dist/checks/shadow-builtin.js +0 -29
- package/dist/checks/shadow-builtin.js.map +0 -1
- package/dist/checks/strcat-usage.d.ts +0 -3
- package/dist/checks/strcat-usage.d.ts.map +0 -1
- package/dist/checks/strcat-usage.js +0 -22
- package/dist/checks/strcat-usage.js.map +0 -1
- package/dist/checks/token-in-url.d.ts.map +0 -1
- package/dist/checks/token-in-url.js.map +0 -1
- package/dist/checks/trailing-ws.d.ts.map +0 -1
- package/dist/checks/trailing-ws.js.map +0 -1
- package/dist/checks/type-check.d.ts +0 -3
- package/dist/checks/type-check.d.ts.map +0 -1
- package/dist/checks/type-check.js +0 -26
- package/dist/checks/type-check.js.map +0 -1
- package/dist/checks/unused-variable.d.ts.map +0 -1
- package/dist/checks/unused-variable.js.map +0 -1
- package/dist/checks/vlax.d.ts.map +0 -1
- package/dist/checks/vlax.js.map +0 -1
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js.map +0 -1
- package/dist/disable.d.ts.map +0 -1
- package/dist/disable.js.map +0 -1
- package/dist/formatters.d.ts.map +0 -1
- package/dist/formatters.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/lib/lint-sbcl.lisp +0 -161
- package/dist/locale.d.ts.map +0 -1
- package/dist/locale.js.map +0 -1
- package/dist/rules.d.ts +0 -9
- package/dist/rules.d.ts.map +0 -1
- package/dist/rules.js +0 -58
- package/dist/rules.js.map +0 -1
- package/dist/runner.d.ts.map +0 -1
- package/dist/runner.js.map +0 -1
- package/dist/sbcl.d.ts.map +0 -1
- package/dist/sbcl.js.map +0 -1
- package/dist/stub-packages.json +0 -41
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/utils.d.ts.map +0 -1
- package/dist/utils.js.map +0 -1
- package/dist/validate.d.ts +0 -8
- package/dist/validate.d.ts.map +0 -1
- package/dist/validate.js +0 -59
- package/dist/validate.js.map +0 -1
- package/dist/watch.d.ts +0 -9
- package/dist/watch.d.ts.map +0 -1
- package/dist/watch.js +0 -109
- package/dist/watch.js.map +0 -1
- package/dist/worker.d.ts.map +0 -1
- package/dist/worker.js.map +0 -1
- 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
|
+
// Last clause with T/t condition: (cond (x y) (T z)) → else branch
|
|
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
|
|
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
|
|
9
|
-
for (
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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,
|
|
16
|
-
|
|
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,
|
|
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,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,
|
|
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
|