@atlisp/lint 0.1.4 → 0.1.6
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/LICENSE +21 -0
- package/README.md +182 -58
- package/atlisp-lint.default.json +31 -1
- package/dist/atlisp-lint.default.json +90 -0
- package/dist/cache.d.ts +2 -2
- package/dist/cache.js +6 -6
- package/dist/checks/append-single.d.ts +3 -0
- package/dist/checks/append-single.js +17 -0
- package/dist/checks/arg-count.d.ts +3 -0
- package/dist/checks/arg-count.js +123 -0
- package/dist/checks/assoc-without-cdr.d.ts +5 -0
- package/dist/checks/assoc-without-cdr.js +32 -0
- package/dist/checks/comment-style.d.ts +3 -0
- package/dist/checks/comment-style.js +24 -0
- package/dist/checks/cond-duplicate.d.ts +5 -0
- package/dist/checks/cond-duplicate.js +52 -0
- package/dist/checks/cond-simplify.d.ts +3 -0
- package/dist/checks/cond-simplify.js +45 -0
- package/dist/checks/constant-condition.js +4 -4
- package/dist/checks/dangerous-calls.js +2 -2
- package/dist/checks/dangling-defun.d.ts +3 -0
- package/dist/checks/dangling-defun.js +10 -28
- package/dist/checks/double-not.js +1 -1
- package/dist/checks/duplicate-defun.d.ts +6 -0
- package/dist/checks/duplicate-defun.js +50 -0
- package/dist/checks/dynamic-doc.d.ts +3 -0
- package/dist/checks/dynamic-doc.js +21 -0
- package/dist/checks/empty-branch.js +1 -1
- package/dist/checks/empty-catch.d.ts +3 -0
- package/dist/checks/empty-catch.js +34 -0
- package/dist/checks/eq-usage.d.ts +3 -0
- package/dist/checks/eq-usage.js +25 -0
- package/dist/checks/error-handling.d.ts +3 -0
- package/dist/checks/error-handling.js +56 -0
- package/dist/checks/extra-parens.d.ts +3 -0
- package/dist/checks/extra-parens.js +45 -0
- package/dist/checks/function-complexity.js +1 -1
- package/dist/checks/function-order.d.ts +3 -0
- package/dist/checks/function-order.js +33 -0
- package/dist/checks/global-naming.d.ts +3 -0
- package/dist/checks/global-naming.js +62 -0
- package/dist/checks/identical-branches.d.ts +5 -0
- package/dist/checks/identical-branches.js +54 -0
- package/dist/checks/index.d.ts +3 -0
- package/dist/checks/index.js +117 -0
- package/dist/checks/lambda-syntax.d.ts +3 -0
- package/dist/checks/lambda-syntax.js +25 -0
- package/dist/checks/long-function-call.d.ts +3 -0
- package/dist/checks/long-function-call.js +54 -0
- package/dist/checks/loop-optimization.d.ts +3 -0
- package/dist/checks/loop-optimization.js +17 -0
- package/dist/checks/magic-number.d.ts +3 -0
- package/dist/checks/magic-number.js +21 -0
- package/dist/checks/misplaced-else.js +1 -1
- package/dist/checks/missing-export.js +2 -2
- package/dist/checks/mixed-indent.d.ts +3 -0
- package/dist/checks/mixed-indent.js +19 -0
- package/dist/checks/module-reg.js +1 -1
- package/dist/checks/multiple-setq.js +1 -1
- package/dist/checks/no-return.d.ts +3 -0
- package/dist/checks/no-return.js +51 -0
- package/dist/checks/nth-usage.d.ts +3 -0
- package/dist/checks/nth-usage.js +17 -0
- package/dist/checks/quote-style.d.ts +3 -0
- package/dist/checks/quote-style.js +25 -0
- package/dist/checks/quote-vs-function.js +1 -1
- package/dist/checks/recursive-call.js +1 -1
- package/dist/checks/redundant-cond.js +2 -2
- package/dist/checks/redundant-if.d.ts +3 -0
- package/dist/checks/redundant-if.js +17 -0
- package/dist/checks/redundant-let.js +1 -1
- package/dist/checks/redundant-nil-else.js +1 -1
- package/dist/checks/redundant-progn.js +1 -1
- package/dist/checks/redundant-quotes.js +1 -1
- package/dist/checks/redundant-setq.js +1 -1
- package/dist/checks/self-compare.js +1 -1
- package/dist/checks/setq-multiple.d.ts +3 -0
- package/dist/checks/setq-multiple.js +17 -0
- package/dist/checks/setq-single-arg.d.ts +5 -0
- package/dist/checks/setq-single-arg.js +30 -0
- package/dist/checks/shadow-builtin.d.ts +3 -0
- package/dist/checks/shadow-builtin.js +77 -0
- package/dist/checks/single-arg-and-or.js +1 -1
- package/dist/checks/strcat-usage.d.ts +3 -0
- package/dist/checks/strcat-usage.js +25 -0
- package/dist/checks/type-check.d.ts +3 -0
- package/dist/checks/type-check.js +26 -0
- package/dist/checks/unused-let.js +1 -1
- package/dist/checks/unused-package-dep.js +3 -3
- package/dist/checks/variable-shadow.js +1 -1
- package/dist/checks/while-constant.d.ts +5 -0
- package/dist/checks/while-constant.js +40 -0
- package/dist/config.d.ts +1 -0
- package/dist/config.js +70 -2
- package/dist/disable.js +1 -1
- package/dist/formatters.d.ts +1 -0
- package/dist/formatters.js +18 -2
- package/dist/index.js +53 -13
- package/dist/lib/lint-sbcl.lisp +161 -0
- package/dist/locale.js +24 -0
- package/dist/presets.d.ts +4 -0
- package/dist/presets.js +158 -0
- package/dist/project.js +37 -6
- package/dist/rules.d.ts +9 -0
- package/dist/rules.js +238 -0
- package/dist/runner.d.ts +2 -0
- package/dist/runner.js +198 -11
- package/dist/sbcl.js +1 -1
- package/dist/stub-packages.json +41 -0
- package/dist/types.d.ts +6 -0
- package/dist/validate.d.ts +8 -0
- package/dist/validate.js +125 -0
- package/dist/watch.d.ts +9 -0
- package/dist/watch.js +113 -0
- package/package.json +1 -1
|
@@ -11,7 +11,7 @@ function checkRedundantNilElse(content, file) {
|
|
|
11
11
|
function checkRedundantNilElseAst(ast, file) {
|
|
12
12
|
const issues = [];
|
|
13
13
|
// Find (if cond then nil) — else branch is nil which is the default
|
|
14
|
-
const ifNodes = (0, parser_1.astFindAll)(ast,
|
|
14
|
+
const ifNodes = (0, parser_1.astFindAll)(ast, n => (0, parser_1.astIsList)(n, 'if'));
|
|
15
15
|
for (const node of ifNodes) {
|
|
16
16
|
if (!node.children || node.children.length !== 4)
|
|
17
17
|
continue;
|
|
@@ -10,7 +10,7 @@ function checkRedundantProgn(content, file) {
|
|
|
10
10
|
}
|
|
11
11
|
function checkRedundantPrognAst(ast, file) {
|
|
12
12
|
const issues = [];
|
|
13
|
-
const prognNodes = (0, parser_1.astFindAll)(ast,
|
|
13
|
+
const prognNodes = (0, parser_1.astFindAll)(ast, n => (0, parser_1.astIsList)(n, 'progn'));
|
|
14
14
|
for (const node of prognNodes) {
|
|
15
15
|
if (!node.children)
|
|
16
16
|
continue;
|
|
@@ -11,7 +11,7 @@ function checkRedundantQuotes(content, file) {
|
|
|
11
11
|
function checkRedundantQuotesAst(ast, file) {
|
|
12
12
|
const issues = [];
|
|
13
13
|
// ''x → (quote (quote x)) — nested quote
|
|
14
|
-
const doubleQuotes = (0, parser_1.astFindAll)(ast,
|
|
14
|
+
const doubleQuotes = (0, parser_1.astFindAll)(ast, n => {
|
|
15
15
|
if (!(0, parser_1.astIsList)(n, 'quote'))
|
|
16
16
|
return false;
|
|
17
17
|
if (!n.children || n.children.length < 2)
|
|
@@ -10,7 +10,7 @@ function checkRedundantSetq(content, file) {
|
|
|
10
10
|
}
|
|
11
11
|
function checkRedundantSetqAst(ast, file) {
|
|
12
12
|
const issues = [];
|
|
13
|
-
const setqNodes = (0, parser_1.astFindAll)(ast,
|
|
13
|
+
const setqNodes = (0, parser_1.astFindAll)(ast, n => (0, parser_1.astIsList)(n, 'setq'));
|
|
14
14
|
for (const node of setqNodes) {
|
|
15
15
|
if (!node.children)
|
|
16
16
|
continue;
|
|
@@ -12,7 +12,7 @@ function checkSelfCompare(content, file) {
|
|
|
12
12
|
function checkSelfCompareAst(ast, file) {
|
|
13
13
|
const issues = [];
|
|
14
14
|
for (const fn of COMPARE_FUNCTIONS) {
|
|
15
|
-
const nodes = (0, parser_1.astFindAll)(ast,
|
|
15
|
+
const nodes = (0, parser_1.astFindAll)(ast, n => (0, parser_1.astIsList)(n, fn));
|
|
16
16
|
for (const node of nodes) {
|
|
17
17
|
if (!node.children)
|
|
18
18
|
continue;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.checkSetqMultiple = checkSetqMultiple;
|
|
4
|
+
const locale_1 = require("../locale");
|
|
5
|
+
const utils_1 = require("../utils");
|
|
6
|
+
function checkSetqMultiple(content, file) {
|
|
7
|
+
const issues = [];
|
|
8
|
+
const lines = content.split('\n');
|
|
9
|
+
for (let i = 0; i < lines.length; i++) {
|
|
10
|
+
const stripped = (0, utils_1.stripLine)(lines[i]);
|
|
11
|
+
if (/\(setq\s+\S+\s+[^\s)]+\)\s*\(setq\b/.test(stripped)) {
|
|
12
|
+
issues.push({ file, line: i + 1, severity: 'warn', rule: 'setq_multiple', message: (0, locale_1.t)('setq_multiple') });
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return issues;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=setq-multiple.js.map
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Issue } from '../types';
|
|
2
|
+
import { AstNode } from '@atlisp/parser';
|
|
3
|
+
export declare function checkSetqSingleArg(content: string, file: string): Issue[];
|
|
4
|
+
export declare function checkSetqSingleArgAst(ast: AstNode, file: string): Issue[];
|
|
5
|
+
//# sourceMappingURL=setq-single-arg.d.ts.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.checkSetqSingleArg = checkSetqSingleArg;
|
|
4
|
+
exports.checkSetqSingleArgAst = checkSetqSingleArgAst;
|
|
5
|
+
const locale_1 = require("../locale");
|
|
6
|
+
const parser_1 = require("@atlisp/parser");
|
|
7
|
+
function checkSetqSingleArg(content, file) {
|
|
8
|
+
const ast = (0, parser_1.parseAst)(content);
|
|
9
|
+
return checkSetqSingleArgAst(ast, file);
|
|
10
|
+
}
|
|
11
|
+
function checkSetqSingleArgAst(ast, file) {
|
|
12
|
+
const issues = [];
|
|
13
|
+
const nodes = (0, parser_1.astFindAll)(ast, n => (0, parser_1.astIsList)(n, 'setq'));
|
|
14
|
+
for (const node of nodes) {
|
|
15
|
+
if (!node.children)
|
|
16
|
+
continue;
|
|
17
|
+
// (setq x) — 2 children: 'setq', x — missing value
|
|
18
|
+
if (node.children.length === 2) {
|
|
19
|
+
issues.push({
|
|
20
|
+
file,
|
|
21
|
+
line: node.pos.line,
|
|
22
|
+
severity: 'warn',
|
|
23
|
+
rule: 'setq_single_arg',
|
|
24
|
+
message: (0, locale_1.t)('setq_single_arg', node.children[1].name || ''),
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return issues;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=setq-single-arg.js.map
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.checkShadowBuiltin = checkShadowBuiltin;
|
|
4
|
+
const locale_1 = require("../locale");
|
|
5
|
+
const utils_1 = require("../utils");
|
|
6
|
+
const BUILTINS = new Set([
|
|
7
|
+
'car',
|
|
8
|
+
'cdr',
|
|
9
|
+
'cons',
|
|
10
|
+
'list',
|
|
11
|
+
'append',
|
|
12
|
+
'length',
|
|
13
|
+
'member',
|
|
14
|
+
'assoc',
|
|
15
|
+
'subst',
|
|
16
|
+
'apply',
|
|
17
|
+
'mapcar',
|
|
18
|
+
'foreach',
|
|
19
|
+
'while',
|
|
20
|
+
'repeat',
|
|
21
|
+
'if',
|
|
22
|
+
'cond',
|
|
23
|
+
'progn',
|
|
24
|
+
'setq',
|
|
25
|
+
'set',
|
|
26
|
+
'quote',
|
|
27
|
+
'function',
|
|
28
|
+
'lambda',
|
|
29
|
+
'defun',
|
|
30
|
+
'princ',
|
|
31
|
+
'print',
|
|
32
|
+
'prompt',
|
|
33
|
+
'getint',
|
|
34
|
+
'getreal',
|
|
35
|
+
'getstring',
|
|
36
|
+
'getpoint',
|
|
37
|
+
'getvar',
|
|
38
|
+
'setvar',
|
|
39
|
+
'command',
|
|
40
|
+
'vlax-',
|
|
41
|
+
'vla-',
|
|
42
|
+
'vl-',
|
|
43
|
+
'ssget',
|
|
44
|
+
'ssname',
|
|
45
|
+
'sslength',
|
|
46
|
+
'entget',
|
|
47
|
+
'entmod',
|
|
48
|
+
'entmake',
|
|
49
|
+
'entdel',
|
|
50
|
+
'entlast',
|
|
51
|
+
'entsel',
|
|
52
|
+
'tblobjname',
|
|
53
|
+
'tblsearch',
|
|
54
|
+
'tblnext',
|
|
55
|
+
'regapp',
|
|
56
|
+
'startapp',
|
|
57
|
+
'vl-registry-write',
|
|
58
|
+
'vl-registry-read',
|
|
59
|
+
'vl-registry-delete',
|
|
60
|
+
'vl-catch-all-apply',
|
|
61
|
+
'vl-catch-all-error-p',
|
|
62
|
+
'vl-load-com',
|
|
63
|
+
'vlax-get-or-create-object',
|
|
64
|
+
]);
|
|
65
|
+
function checkShadowBuiltin(content, file) {
|
|
66
|
+
const issues = [];
|
|
67
|
+
const lines = content.split('\n');
|
|
68
|
+
for (let i = 0; i < lines.length; i++) {
|
|
69
|
+
const stripped = (0, utils_1.stripLine)(lines[i]);
|
|
70
|
+
const m = stripped.match(/\(defun\s+(\S+)\b/);
|
|
71
|
+
if (m && BUILTINS.has(m[1].toLowerCase())) {
|
|
72
|
+
issues.push({ file, line: i + 1, severity: 'warn', rule: 'shadow_builtin', message: (0, locale_1.t)('shadow_builtin', m[1]) });
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return issues;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=shadow-builtin.js.map
|
|
@@ -11,7 +11,7 @@ function checkSingleArgAndOr(content, file) {
|
|
|
11
11
|
function checkSingleArgAndOrAst(ast, file) {
|
|
12
12
|
const issues = [];
|
|
13
13
|
for (const form of ['and', 'or']) {
|
|
14
|
-
const nodes = (0, parser_1.astFindAll)(ast,
|
|
14
|
+
const nodes = (0, parser_1.astFindAll)(ast, n => (0, parser_1.astIsList)(n, form));
|
|
15
15
|
for (const node of nodes) {
|
|
16
16
|
if (!node.children)
|
|
17
17
|
continue;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.checkStrcatUsage = checkStrcatUsage;
|
|
4
|
+
const locale_1 = require("../locale");
|
|
5
|
+
const utils_1 = require("../utils");
|
|
6
|
+
function checkStrcatUsage(content, file) {
|
|
7
|
+
const issues = [];
|
|
8
|
+
const lines = content.split('\n');
|
|
9
|
+
for (let i = 0; i < lines.length; i++) {
|
|
10
|
+
const stripped = (0, utils_1.stripLineRaw)(lines[i]);
|
|
11
|
+
// Check for (+ "str" ...) pattern
|
|
12
|
+
const m = stripped.match(/\(\+\s+"[^"]*"/);
|
|
13
|
+
if (m) {
|
|
14
|
+
issues.push({
|
|
15
|
+
file,
|
|
16
|
+
line: i + 1,
|
|
17
|
+
severity: 'warn',
|
|
18
|
+
rule: 'strcat_usage',
|
|
19
|
+
message: (0, locale_1.t)('strcat_usage'),
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return issues;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=strcat-usage.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.checkTypeCheck = checkTypeCheck;
|
|
4
|
+
const locale_1 = require("../locale");
|
|
5
|
+
const utils_1 = require("../utils");
|
|
6
|
+
function checkTypeCheck(content, file) {
|
|
7
|
+
const issues = [];
|
|
8
|
+
const lines = content.split('\n');
|
|
9
|
+
for (let i = 0; i < lines.length; i++) {
|
|
10
|
+
const stripped = (0, utils_1.stripLine)(lines[i]);
|
|
11
|
+
const m = stripped.match(/\(setq\s+\S+\s+\(getvar\b/);
|
|
12
|
+
if (m) {
|
|
13
|
+
const varName = m[0].match(/\(setq\s+(\S+)/)?.[1] || '';
|
|
14
|
+
if (!varName)
|
|
15
|
+
continue;
|
|
16
|
+
const body = lines.slice(i, i + 5).join('\n');
|
|
17
|
+
const typeChk = '(type ' + varName;
|
|
18
|
+
const eqTypeChk = '(= (type ' + varName;
|
|
19
|
+
if (!body.includes(typeChk) && !body.includes(eqTypeChk)) {
|
|
20
|
+
issues.push({ file, line: i + 1, severity: 'warn', rule: 'type_check', message: (0, locale_1.t)('type_check', varName) });
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return issues;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=type-check.js.map
|
|
@@ -10,7 +10,7 @@ function checkUnusedLetBinding(content, file) {
|
|
|
10
10
|
}
|
|
11
11
|
function checkUnusedLetBindingAst(ast, file) {
|
|
12
12
|
const issues = [];
|
|
13
|
-
const letNodes = (0, parser_1.astFindAll)(ast,
|
|
13
|
+
const letNodes = (0, parser_1.astFindAll)(ast, n => (0, parser_1.astIsList)(n, 'let'));
|
|
14
14
|
for (const node of letNodes) {
|
|
15
15
|
if (!node.children || node.children.length < 2)
|
|
16
16
|
continue;
|
|
@@ -41,7 +41,7 @@ function checkUnusedPackageDep(file) {
|
|
|
41
41
|
const issues = [];
|
|
42
42
|
const content = fs.readFileSync(file, 'utf-8');
|
|
43
43
|
const ast = (0, parser_1.parseAst)(content);
|
|
44
|
-
const inPackageNodes = (0, parser_1.astFindAll)(ast,
|
|
44
|
+
const inPackageNodes = (0, parser_1.astFindAll)(ast, n => (0, parser_1.astIsList)(n, 'in-package'));
|
|
45
45
|
if (inPackageNodes.length === 0)
|
|
46
46
|
return issues;
|
|
47
47
|
const allPackages = new Set();
|
|
@@ -51,7 +51,7 @@ function checkUnusedPackageDep(file) {
|
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
const usedSymbols = new Set();
|
|
54
|
-
const allLists = (0, parser_1.astFindAll)(ast,
|
|
54
|
+
const allLists = (0, parser_1.astFindAll)(ast, n => n.type === 'list');
|
|
55
55
|
for (const node of allLists) {
|
|
56
56
|
if (!node.children || node.children.length === 0)
|
|
57
57
|
continue;
|
|
@@ -78,7 +78,7 @@ function checkUnusedPackageDep(file) {
|
|
|
78
78
|
allPackages.delete(mainPackage);
|
|
79
79
|
for (const pkg of allPackages) {
|
|
80
80
|
if (!usedSymbols.has(pkg)) {
|
|
81
|
-
const node = inPackageNodes.find(
|
|
81
|
+
const node = inPackageNodes.find(n => n.children && n.children.length >= 2 && (0, parser_1.astIsSymbol)(n.children[1]) && n.children[1].name === pkg);
|
|
82
82
|
issues.push({
|
|
83
83
|
file,
|
|
84
84
|
line: node ? node.pos.line : 1,
|
|
@@ -10,7 +10,7 @@ function checkVariableShadow(content, file) {
|
|
|
10
10
|
}
|
|
11
11
|
function checkVariableShadowAst(ast, file) {
|
|
12
12
|
const issues = [];
|
|
13
|
-
const letNodes = (0, parser_1.astFindAll)(ast,
|
|
13
|
+
const letNodes = (0, parser_1.astFindAll)(ast, n => (0, parser_1.astIsList)(n, 'let'));
|
|
14
14
|
for (const node of letNodes) {
|
|
15
15
|
if (!node.children || node.children.length < 2)
|
|
16
16
|
continue;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Issue } from '../types';
|
|
2
|
+
import { AstNode } from '@atlisp/parser';
|
|
3
|
+
export declare function checkWhileConstant(content: string, file: string): Issue[];
|
|
4
|
+
export declare function checkWhileConstantAst(ast: AstNode, file: string): Issue[];
|
|
5
|
+
//# sourceMappingURL=while-constant.d.ts.map
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.checkWhileConstant = checkWhileConstant;
|
|
4
|
+
exports.checkWhileConstantAst = checkWhileConstantAst;
|
|
5
|
+
const locale_1 = require("../locale");
|
|
6
|
+
const parser_1 = require("@atlisp/parser");
|
|
7
|
+
function checkWhileConstant(content, file) {
|
|
8
|
+
const ast = (0, parser_1.parseAst)(content);
|
|
9
|
+
return checkWhileConstantAst(ast, file);
|
|
10
|
+
}
|
|
11
|
+
function checkWhileConstantAst(ast, file) {
|
|
12
|
+
const issues = [];
|
|
13
|
+
const whileNodes = (0, parser_1.astFindAll)(ast, n => (0, parser_1.astIsList)(n, 'while'));
|
|
14
|
+
for (const node of whileNodes) {
|
|
15
|
+
if (!node.children || node.children.length < 2)
|
|
16
|
+
continue;
|
|
17
|
+
const cond = node.children[1];
|
|
18
|
+
// Check for constant conditions: nil, T, 1, 0, etc.
|
|
19
|
+
if (cond.type === 'symbol' && (cond.name === 'nil' || cond.name === 'T')) {
|
|
20
|
+
issues.push({
|
|
21
|
+
file,
|
|
22
|
+
line: node.pos.line,
|
|
23
|
+
severity: 'warn',
|
|
24
|
+
rule: 'while_constant',
|
|
25
|
+
message: (0, locale_1.t)('while_constant', cond.name),
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
else if (cond.type === 'number') {
|
|
29
|
+
issues.push({
|
|
30
|
+
file,
|
|
31
|
+
line: node.pos.line,
|
|
32
|
+
severity: 'warn',
|
|
33
|
+
rule: 'while_constant',
|
|
34
|
+
message: (0, locale_1.t)('while_constant', String(cond.value)),
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return issues;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=while-constant.js.map
|
package/dist/config.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { LintConfig } from './types';
|
|
2
2
|
export declare function loadConfig(configPath?: string): LintConfig;
|
|
3
|
+
export declare function getCheckSeverity(config: LintConfig, rule: string): string;
|
|
3
4
|
export declare function findOverrides(filepath: string): Partial<LintConfig> | null;
|
|
4
5
|
export declare function mergeOverrides(base: LintConfig, overrides: Partial<LintConfig>): LintConfig;
|
|
5
6
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.js
CHANGED
|
@@ -34,10 +34,12 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.loadConfig = loadConfig;
|
|
37
|
+
exports.getCheckSeverity = getCheckSeverity;
|
|
37
38
|
exports.findOverrides = findOverrides;
|
|
38
39
|
exports.mergeOverrides = mergeOverrides;
|
|
39
40
|
const fs = __importStar(require("fs"));
|
|
40
41
|
const path = __importStar(require("path"));
|
|
42
|
+
const presets_1 = require("./presets");
|
|
41
43
|
const DEFAULT_CONFIG = {
|
|
42
44
|
locale: 'zh',
|
|
43
45
|
source: {
|
|
@@ -56,14 +58,69 @@ const DEFAULT_CONFIG = {
|
|
|
56
58
|
token_in_url: 'warn',
|
|
57
59
|
open_without_close: 'warn',
|
|
58
60
|
bare_function_names: 'warn',
|
|
59
|
-
trailing_whitespace: 'warn',
|
|
60
61
|
line_length: 'warn',
|
|
61
62
|
function_complexity: 'warn',
|
|
62
63
|
parameter_naming: 'warn',
|
|
63
64
|
unused_variable: 'warn',
|
|
64
65
|
missing_doc: 'warn',
|
|
66
|
+
trailing_whitespace: 'warn',
|
|
65
67
|
module_registration: 'off',
|
|
66
68
|
namespace_header: 'off',
|
|
69
|
+
unused_parameter: 'warn',
|
|
70
|
+
constant_condition: 'warn',
|
|
71
|
+
redundant_progn: 'warn',
|
|
72
|
+
empty_branch: 'warn',
|
|
73
|
+
unused_let_binding: 'warn',
|
|
74
|
+
recursive_call: 'warn',
|
|
75
|
+
variable_shadow: 'warn',
|
|
76
|
+
redundant_cond: 'warn',
|
|
77
|
+
unused_local_fun: 'warn',
|
|
78
|
+
multiple_setq: 'warn',
|
|
79
|
+
redundant_quotes: 'warn',
|
|
80
|
+
trailing_paren: 'warn',
|
|
81
|
+
empty_comment: 'warn',
|
|
82
|
+
redundant_setq: 'warn',
|
|
83
|
+
redundant_nil_else: 'warn',
|
|
84
|
+
single_arg_and_or: 'warn',
|
|
85
|
+
redundant_let: 'warn',
|
|
86
|
+
self_compare: 'warn',
|
|
87
|
+
misplaced_else: 'warn',
|
|
88
|
+
quote_vs_function: 'warn',
|
|
89
|
+
commented_code: 'warn',
|
|
90
|
+
double_not: 'warn',
|
|
91
|
+
setq_single_arg: 'warn',
|
|
92
|
+
assoc_without_cdr: 'warn',
|
|
93
|
+
identical_branches: 'warn',
|
|
94
|
+
while_constant: 'warn',
|
|
95
|
+
cond_duplicate: 'warn',
|
|
96
|
+
duplicate_defun: 'warn',
|
|
97
|
+
dangling_defun: 'warn',
|
|
98
|
+
missing_export: 'warn',
|
|
99
|
+
unused_package_dep: 'warn',
|
|
100
|
+
error_handling: 'warn',
|
|
101
|
+
global_naming: 'warn',
|
|
102
|
+
extra_parens: 'warn',
|
|
103
|
+
arg_count: 'warn',
|
|
104
|
+
strcat_usage: 'warn',
|
|
105
|
+
cond_simplify: 'warn',
|
|
106
|
+
quote_style: 'warn',
|
|
107
|
+
eq_usage: 'warn',
|
|
108
|
+
lambda_syntax: 'warn',
|
|
109
|
+
comment_style: 'warn',
|
|
110
|
+
empty_catch: 'warn',
|
|
111
|
+
nth_usage: 'warn',
|
|
112
|
+
append_single: 'warn',
|
|
113
|
+
setq_multiple: 'warn',
|
|
114
|
+
function_order: 'off',
|
|
115
|
+
magic_number: 'off',
|
|
116
|
+
mixed_indent: 'warn',
|
|
117
|
+
long_function_call: 'warn',
|
|
118
|
+
no_return: 'warn',
|
|
119
|
+
shadow_builtin: 'warn',
|
|
120
|
+
dynamic_doc: 'warn',
|
|
121
|
+
loop_optimization: 'off',
|
|
122
|
+
type_check: 'off',
|
|
123
|
+
redundant_if: 'warn',
|
|
67
124
|
},
|
|
68
125
|
line_length: {
|
|
69
126
|
max: 100,
|
|
@@ -111,9 +168,17 @@ function loadConfig(configPath) {
|
|
|
111
168
|
}
|
|
112
169
|
const raw = fs.readFileSync(absPath, 'utf-8');
|
|
113
170
|
const user = JSON.parse(raw);
|
|
114
|
-
//
|
|
171
|
+
// Start from default config
|
|
115
172
|
const merged = JSON.parse(JSON.stringify(DEFAULT_CONFIG));
|
|
173
|
+
// Apply preset if specified (preset applies before user overrides)
|
|
174
|
+
const preset = user.preset;
|
|
175
|
+
if (preset && presets_1.PRESETS[preset]) {
|
|
176
|
+
deepMerge(merged, presets_1.PRESETS[preset]);
|
|
177
|
+
}
|
|
178
|
+
// Apply user overrides (user settings take precedence)
|
|
116
179
|
deepMerge(merged, user);
|
|
180
|
+
// Remove non-config keys
|
|
181
|
+
delete merged.preset;
|
|
117
182
|
return merged;
|
|
118
183
|
}
|
|
119
184
|
return JSON.parse(JSON.stringify(DEFAULT_CONFIG));
|
|
@@ -133,6 +198,9 @@ function deepMerge(target, source) {
|
|
|
133
198
|
}
|
|
134
199
|
}
|
|
135
200
|
}
|
|
201
|
+
function getCheckSeverity(config, rule) {
|
|
202
|
+
return config.checks[rule] || 'off';
|
|
203
|
+
}
|
|
136
204
|
function findOverrides(filepath) {
|
|
137
205
|
const dir = path.dirname(filepath);
|
|
138
206
|
const configPath = path.join(dir, '.atlisp-lint.json');
|
package/dist/disable.js
CHANGED
package/dist/formatters.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Issue } from './types';
|
|
2
2
|
export declare function formatDefault(issues: Issue[], fileContents?: Map<string, string>): string;
|
|
3
|
+
export declare function formatHtml(issues: Issue[], errorCount: number, warningCount: number): string;
|
|
3
4
|
export declare function formatJson(issues: Issue[], errorCount?: number, warningCount?: number): string;
|
|
4
5
|
//# sourceMappingURL=formatters.d.ts.map
|
package/dist/formatters.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.formatDefault = formatDefault;
|
|
4
|
+
exports.formatHtml = formatHtml;
|
|
4
5
|
exports.formatJson = formatJson;
|
|
5
6
|
const locale_1 = require("./locale");
|
|
6
7
|
const colors = {
|
|
@@ -68,11 +69,26 @@ function formatDefault(issues, fileContents) {
|
|
|
68
69
|
}
|
|
69
70
|
return lines.join('\n');
|
|
70
71
|
}
|
|
72
|
+
function formatHtml(issues, errorCount, warningCount) {
|
|
73
|
+
let html = `<!DOCTYPE html>
|
|
74
|
+
<html lang="en">
|
|
75
|
+
<head><meta charset="UTF-8"><title>@atlisp/lint Report</title></head>
|
|
76
|
+
<body>
|
|
77
|
+
<h1>@atlisp/lint Report</h1>
|
|
78
|
+
<p>${errorCount} error(s), ${warningCount} warning(s)</p>
|
|
79
|
+
<ul>
|
|
80
|
+
`;
|
|
81
|
+
for (const iss of issues) {
|
|
82
|
+
html += ` <li>${iss.severity}: ${iss.file}:${iss.line} — ${iss.message}</li>\n`;
|
|
83
|
+
}
|
|
84
|
+
html += '</ul>\n</body>\n</html>';
|
|
85
|
+
return html;
|
|
86
|
+
}
|
|
71
87
|
function formatJson(issues, errorCount, warningCount) {
|
|
72
88
|
return JSON.stringify({
|
|
73
89
|
issues,
|
|
74
|
-
error_count: errorCount ?? issues.filter(
|
|
75
|
-
warning_count: warningCount ?? issues.filter(
|
|
90
|
+
error_count: errorCount ?? issues.filter(i => i.severity === 'error').length,
|
|
91
|
+
warning_count: warningCount ?? issues.filter(i => i.severity === 'warn').length,
|
|
76
92
|
}, null, 2);
|
|
77
93
|
}
|
|
78
94
|
//# sourceMappingURL=formatters.js.map
|