@atlisp/lint 0.1.5 → 0.1.8
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 +219 -58
- package/atlisp-lint.default.json +32 -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/format-indent.d.ts +3 -0
- package/dist/checks/format-indent.js +29 -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-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 +71 -2
- package/dist/disable.js +1 -1
- package/dist/formatter.d.ts +2 -0
- package/dist/formatter.js +51 -0
- package/dist/formatters.d.ts +1 -0
- package/dist/formatters.js +18 -2
- package/dist/index.js +172 -32
- package/dist/lib/lint-sbcl.lisp +161 -0
- package/dist/locale.js +76 -0
- package/dist/presets.d.ts +4 -0
- package/dist/presets.js +159 -0
- package/dist/project.js +37 -6
- package/dist/rules.d.ts +9 -0
- package/dist/rules.js +239 -0
- package/dist/runner.d.ts +2 -0
- package/dist/runner.js +329 -12
- 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 +126 -0
- package/dist/watch.d.ts +9 -0
- package/dist/watch.js +113 -0
- package/package.json +1 -1
|
@@ -12,7 +12,7 @@ function checkMultipleSetqAst(ast, file) {
|
|
|
12
12
|
const issues = [];
|
|
13
13
|
// Find all parent lists that contain at least one setq
|
|
14
14
|
const parents = new Set();
|
|
15
|
-
const setqNodes = (0, parser_1.astFindAll)(ast,
|
|
15
|
+
const setqNodes = (0, parser_1.astFindAll)(ast, n => (0, parser_1.astIsList)(n, 'setq'));
|
|
16
16
|
for (const n of setqNodes) {
|
|
17
17
|
if (n.parent)
|
|
18
18
|
parents.add(n.parent);
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.checkNoReturn = checkNoReturn;
|
|
4
|
+
const locale_1 = require("../locale");
|
|
5
|
+
const utils_1 = require("../utils");
|
|
6
|
+
function checkNoReturn(content, file) {
|
|
7
|
+
const issues = [];
|
|
8
|
+
const lines = content.split('\n');
|
|
9
|
+
let inDefun = false;
|
|
10
|
+
let defunName = '';
|
|
11
|
+
let defunStart = 0;
|
|
12
|
+
let depth = 0;
|
|
13
|
+
let hasReturn = false;
|
|
14
|
+
for (let i = 0; i < lines.length; i++) {
|
|
15
|
+
const stripped = (0, utils_1.stripLine)(lines[i]);
|
|
16
|
+
if (!inDefun) {
|
|
17
|
+
const m = stripped.match(/\(defun\s+(\S+)/);
|
|
18
|
+
if (m) {
|
|
19
|
+
inDefun = true;
|
|
20
|
+
defunName = m[1];
|
|
21
|
+
defunStart = i + 1;
|
|
22
|
+
depth = 0;
|
|
23
|
+
hasReturn = false;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (inDefun) {
|
|
27
|
+
for (const ch of stripped) {
|
|
28
|
+
if (ch === '(')
|
|
29
|
+
depth++;
|
|
30
|
+
else if (ch === ')')
|
|
31
|
+
depth--;
|
|
32
|
+
}
|
|
33
|
+
if (stripped.trim().startsWith('(') && !stripped.includes('defun'))
|
|
34
|
+
hasReturn = true;
|
|
35
|
+
if (depth === 0 && defunName && !defunName.startsWith('c:')) {
|
|
36
|
+
if (!hasReturn) {
|
|
37
|
+
issues.push({
|
|
38
|
+
file,
|
|
39
|
+
line: defunStart,
|
|
40
|
+
severity: 'warn',
|
|
41
|
+
rule: 'no_return',
|
|
42
|
+
message: (0, locale_1.t)('no_return', defunName),
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
inDefun = false;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return issues;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=no-return.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.checkNthUsage = checkNthUsage;
|
|
4
|
+
const locale_1 = require("../locale");
|
|
5
|
+
const utils_1 = require("../utils");
|
|
6
|
+
function checkNthUsage(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 (/\(nth\s+0\b/.test(stripped)) {
|
|
12
|
+
issues.push({ file, line: i + 1, severity: 'warn', rule: 'nth_usage', message: (0, locale_1.t)('nth_usage') });
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return issues;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=nth-usage.js.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.checkQuoteStyle = checkQuoteStyle;
|
|
4
|
+
const locale_1 = require("../locale");
|
|
5
|
+
const utils_1 = require("../utils");
|
|
6
|
+
function checkQuoteStyle(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
|
+
// Detect (quote ...) that could be '
|
|
12
|
+
const m = stripped.match(/\(quote\s+/);
|
|
13
|
+
if (m) {
|
|
14
|
+
issues.push({
|
|
15
|
+
file,
|
|
16
|
+
line: i + 1,
|
|
17
|
+
severity: 'warn',
|
|
18
|
+
rule: 'quote_style',
|
|
19
|
+
message: (0, locale_1.t)('quote_style'),
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return issues;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=quote-style.js.map
|
|
@@ -22,7 +22,7 @@ function checkQuoteVsFunction(content, file) {
|
|
|
22
22
|
}
|
|
23
23
|
function checkQuoteVsFunctionAst(ast, file) {
|
|
24
24
|
const issues = [];
|
|
25
|
-
const quotedLambdas = (0, parser_1.astFindAll)(ast,
|
|
25
|
+
const quotedLambdas = (0, parser_1.astFindAll)(ast, n => {
|
|
26
26
|
if (!(0, parser_1.astIsList)(n, 'quote'))
|
|
27
27
|
return false;
|
|
28
28
|
if (!n.children || n.children.length < 2)
|
|
@@ -10,7 +10,7 @@ function checkRecursiveCall(content, file) {
|
|
|
10
10
|
}
|
|
11
11
|
function checkRecursiveCallAst(ast, file) {
|
|
12
12
|
const issues = [];
|
|
13
|
-
const defuns = (0, parser_1.astFindAll)(ast,
|
|
13
|
+
const defuns = (0, parser_1.astFindAll)(ast, n => (0, parser_1.astIsList)(n, 'defun'));
|
|
14
14
|
for (const defun of defuns) {
|
|
15
15
|
if (!defun.children || defun.children.length < 3)
|
|
16
16
|
continue;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.checkRedundantIf = checkRedundantIf;
|
|
4
|
+
const locale_1 = require("../locale");
|
|
5
|
+
const utils_1 = require("../utils");
|
|
6
|
+
function checkRedundantIf(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 (/\((if|when|unless)\s+\S+\s+\(progn\b/.test(stripped)) {
|
|
12
|
+
issues.push({ file, line: i + 1, severity: 'warn', rule: 'redundant_if', message: (0, locale_1.t)('redundant_if') });
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return issues;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=redundant-if.js.map
|
|
@@ -10,7 +10,7 @@ function checkRedundantLet(content, file) {
|
|
|
10
10
|
}
|
|
11
11
|
function checkRedundantLetAst(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;
|
|
@@ -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
|