@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
package/dist/runner.js
CHANGED
|
@@ -33,62 +33,218 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.
|
|
36
|
+
exports.runChecks = runChecks;
|
|
37
|
+
exports.runChecksWithVisitor = runChecksWithVisitor;
|
|
37
38
|
exports.lintFiles = lintFiles;
|
|
38
39
|
exports.lintFilesParallel = lintFilesParallel;
|
|
39
40
|
exports.fixFile = fixFile;
|
|
40
|
-
exports.clearCache = clearCache;
|
|
41
41
|
const fs = __importStar(require("fs"));
|
|
42
42
|
const path = __importStar(require("path"));
|
|
43
43
|
const worker_threads_1 = require("worker_threads");
|
|
44
44
|
const os = __importStar(require("os"));
|
|
45
|
-
const
|
|
45
|
+
const encoding_1 = require("./checks/encoding");
|
|
46
|
+
const parens_1 = require("./checks/parens");
|
|
47
|
+
const cl_syntax_1 = require("./checks/cl-syntax");
|
|
48
|
+
const dangerous_calls_1 = require("./checks/dangerous-calls");
|
|
49
|
+
const vlax_1 = require("./checks/vlax");
|
|
50
|
+
const token_in_url_1 = require("./checks/token-in-url");
|
|
51
|
+
const open_close_1 = require("./checks/open-close");
|
|
52
|
+
const bare_names_1 = require("./checks/bare-names");
|
|
53
|
+
const module_reg_1 = require("./checks/module-reg");
|
|
54
|
+
const namespace_header_1 = require("./checks/namespace-header");
|
|
55
|
+
const trailing_ws_1 = require("./checks/trailing-ws");
|
|
56
|
+
const line_length_1 = require("./checks/line-length");
|
|
57
|
+
const function_complexity_1 = require("./checks/function-complexity");
|
|
58
|
+
const parameter_naming_1 = require("./checks/parameter-naming");
|
|
59
|
+
const unused_variable_1 = require("./checks/unused-variable");
|
|
60
|
+
const missing_doc_1 = require("./checks/missing-doc");
|
|
61
|
+
const unused_param_1 = require("./checks/unused-param");
|
|
62
|
+
const constant_condition_1 = require("./checks/constant-condition");
|
|
63
|
+
const redundant_progn_1 = require("./checks/redundant-progn");
|
|
64
|
+
const empty_branch_1 = require("./checks/empty-branch");
|
|
65
|
+
const unused_let_1 = require("./checks/unused-let");
|
|
66
|
+
const recursive_call_1 = require("./checks/recursive-call");
|
|
67
|
+
const variable_shadow_1 = require("./checks/variable-shadow");
|
|
68
|
+
const redundant_cond_1 = require("./checks/redundant-cond");
|
|
69
|
+
const unused_local_fun_1 = require("./checks/unused-local-fun");
|
|
70
|
+
const multiple_setq_1 = require("./checks/multiple-setq");
|
|
71
|
+
const redundant_quotes_1 = require("./checks/redundant-quotes");
|
|
72
|
+
const trailing_paren_1 = require("./checks/trailing-paren");
|
|
73
|
+
const empty_comments_1 = require("./checks/empty-comments");
|
|
74
|
+
const redundant_setq_1 = require("./checks/redundant-setq");
|
|
75
|
+
const redundant_nil_else_1 = require("./checks/redundant-nil-else");
|
|
76
|
+
const single_arg_and_or_1 = require("./checks/single-arg-and-or");
|
|
77
|
+
const redundant_let_1 = require("./checks/redundant-let");
|
|
78
|
+
const self_compare_1 = require("./checks/self-compare");
|
|
79
|
+
const misplaced_else_1 = require("./checks/misplaced-else");
|
|
80
|
+
const quote_vs_function_1 = require("./checks/quote-vs-function");
|
|
81
|
+
const commented_code_1 = require("./checks/commented-code");
|
|
82
|
+
const double_not_1 = require("./checks/double-not");
|
|
46
83
|
const config_1 = require("./config");
|
|
47
84
|
const locale_1 = require("./locale");
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
.
|
|
63
|
-
|
|
85
|
+
const disable_1 = require("./disable");
|
|
86
|
+
const parser_1 = require("@atlisp/parser");
|
|
87
|
+
function runChecks(content, file, config) {
|
|
88
|
+
const issues = [];
|
|
89
|
+
const disableMap = (0, disable_1.parseDisableComments)(content);
|
|
90
|
+
// Parse AST once for all checks that need it
|
|
91
|
+
const ast = (0, parser_1.parseAst)(content);
|
|
92
|
+
function addIfEnabled(rule, fn) {
|
|
93
|
+
const severity = config.checks[rule];
|
|
94
|
+
if (severity === 'off')
|
|
95
|
+
return;
|
|
96
|
+
const results = fn();
|
|
97
|
+
for (const r of results) {
|
|
98
|
+
if (!(0, disable_1.isDisabled)(r.rule, r.line, disableMap)) {
|
|
99
|
+
issues.push(r);
|
|
100
|
+
}
|
|
64
101
|
}
|
|
65
|
-
catch { /* skip invalid patterns */ }
|
|
66
102
|
}
|
|
67
|
-
|
|
103
|
+
addIfEnabled('encoding', () => (0, encoding_1.checkEncoding)(content, file));
|
|
104
|
+
addIfEnabled('parens', () => (0, parens_1.checkParens)(content, file));
|
|
105
|
+
addIfEnabled('cl_syntax', () => (0, cl_syntax_1.checkClSyntax)(content, file, config.cl_syntax.keywords));
|
|
106
|
+
addIfEnabled('quit_exit', () => (0, dangerous_calls_1.checkDangerousCallsAst)(ast, file, config.dangerous_calls));
|
|
107
|
+
addIfEnabled('vlax_without_loading', () => (0, vlax_1.checkVlaxWithoutLoading)(content, file));
|
|
108
|
+
addIfEnabled('token_in_url', () => (0, token_in_url_1.checkTokenInUrl)(content, file));
|
|
109
|
+
addIfEnabled('open_without_close', () => (0, open_close_1.checkOpenWithoutCloseAst)(ast, file));
|
|
110
|
+
addIfEnabled('bare_function_names', () => (0, bare_names_1.checkBareFunctionNames)(content, file, config.bare_function_names.allowlist, config.bare_function_names.namespace_pattern));
|
|
111
|
+
addIfEnabled('module_registration', () => (0, module_reg_1.checkModuleRegistration)(content, file, file, config.module_registration));
|
|
112
|
+
addIfEnabled('namespace_header', () => (0, namespace_header_1.checkNamespaceHeader)(content, file, config.namespace_header));
|
|
113
|
+
addIfEnabled('line_length', () => (0, line_length_1.checkLineLength)(content, file, config.line_length.max, config.line_length.tab_width));
|
|
114
|
+
addIfEnabled('function_complexity', () => (0, function_complexity_1.checkFunctionComplexityAst)(ast, file, config.function_complexity.max_lines, config.function_complexity.max_nesting));
|
|
115
|
+
addIfEnabled('parameter_naming', () => (0, parameter_naming_1.checkParameterNamingAst)(ast, file));
|
|
116
|
+
addIfEnabled('unused_variable', () => (0, unused_variable_1.checkUnusedVariableAst)(ast, file));
|
|
117
|
+
addIfEnabled('missing_doc', () => (0, missing_doc_1.checkMissingDoc)(content, file));
|
|
118
|
+
addIfEnabled('trailing_whitespace', () => (0, trailing_ws_1.checkTrailingWhitespace)(content, file));
|
|
119
|
+
addIfEnabled('unused_parameter', () => (0, unused_param_1.checkUnusedParameterAst)(ast, file));
|
|
120
|
+
addIfEnabled('constant_condition', () => (0, constant_condition_1.checkConstantConditionAst)(ast, file));
|
|
121
|
+
addIfEnabled('redundant_progn', () => (0, redundant_progn_1.checkRedundantPrognAst)(ast, file));
|
|
122
|
+
addIfEnabled('empty_branch', () => (0, empty_branch_1.checkEmptyBranchAst)(ast, file));
|
|
123
|
+
addIfEnabled('unused_let_binding', () => (0, unused_let_1.checkUnusedLetBindingAst)(ast, file));
|
|
124
|
+
addIfEnabled('recursive_call', () => (0, recursive_call_1.checkRecursiveCallAst)(ast, file));
|
|
125
|
+
addIfEnabled('variable_shadow', () => (0, variable_shadow_1.checkVariableShadowAst)(ast, file));
|
|
126
|
+
addIfEnabled('redundant_cond', () => (0, redundant_cond_1.checkRedundantCondAst)(ast, file));
|
|
127
|
+
addIfEnabled('unused_local_fun', () => (0, unused_local_fun_1.checkUnusedLocalFunAst)(ast, file));
|
|
128
|
+
addIfEnabled('multiple_setq', () => (0, multiple_setq_1.checkMultipleSetqAst)(ast, file));
|
|
129
|
+
addIfEnabled('redundant_quotes', () => (0, redundant_quotes_1.checkRedundantQuotesAst)(ast, file));
|
|
130
|
+
addIfEnabled('trailing_paren', () => (0, trailing_paren_1.checkTrailingParen)(content, file));
|
|
131
|
+
addIfEnabled('empty_comment', () => (0, empty_comments_1.checkEmptyComments)(content, file));
|
|
132
|
+
addIfEnabled('redundant_setq', () => (0, redundant_setq_1.checkRedundantSetqAst)(ast, file));
|
|
133
|
+
addIfEnabled('redundant_nil_else', () => (0, redundant_nil_else_1.checkRedundantNilElseAst)(ast, file));
|
|
134
|
+
addIfEnabled('single_arg_and_or', () => (0, single_arg_and_or_1.checkSingleArgAndOrAst)(ast, file));
|
|
135
|
+
addIfEnabled('redundant_let', () => (0, redundant_let_1.checkRedundantLetAst)(ast, file));
|
|
136
|
+
addIfEnabled('self_compare', () => (0, self_compare_1.checkSelfCompareAst)(ast, file));
|
|
137
|
+
addIfEnabled('misplaced_else', () => (0, misplaced_else_1.checkMisplacedElseAst)(ast, file));
|
|
138
|
+
addIfEnabled('quote_vs_function', () => (0, quote_vs_function_1.checkQuoteVsFunctionAst)(ast, file));
|
|
139
|
+
addIfEnabled('commented_code', () => (0, commented_code_1.checkCommentedCode)(content, file));
|
|
140
|
+
addIfEnabled('double_not', () => (0, double_not_1.checkDoubleNotAst)(ast, file));
|
|
141
|
+
return issues;
|
|
68
142
|
}
|
|
69
|
-
|
|
143
|
+
/** Single-pass visitor-based runChecks using AstVisitor */
|
|
144
|
+
function runChecksWithVisitor(content, file, config) {
|
|
145
|
+
const issues = [];
|
|
146
|
+
const disableMap = (0, disable_1.parseDisableComments)(content);
|
|
147
|
+
const ast = (0, parser_1.parseAst)(content);
|
|
148
|
+
const visitor = new parser_1.AstVisitor();
|
|
149
|
+
const checks = config.checks;
|
|
150
|
+
function addIssue(rule, line, severity, message) {
|
|
151
|
+
if (severity === 'off')
|
|
152
|
+
return;
|
|
153
|
+
if (!(0, disable_1.isDisabled)(rule, line, disableMap)) {
|
|
154
|
+
issues.push({ file, line, severity: severity, rule, message });
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// Register all AST-based checks as visitor handlers
|
|
158
|
+
if (checks['redundant_quotes'] !== 'off') {
|
|
159
|
+
visitor.on('quote', (node) => {
|
|
160
|
+
if (node.children &&
|
|
161
|
+
node.children.length >= 2 &&
|
|
162
|
+
node.children[1].type === 'list' &&
|
|
163
|
+
node.children[1].children &&
|
|
164
|
+
node.children[1].children.length > 0 &&
|
|
165
|
+
node.children[1].children[0].type === 'symbol' &&
|
|
166
|
+
node.children[1].children[0].name === 'quote') {
|
|
167
|
+
addIssue('redundant_quotes', node.pos.line, checks['redundant_quotes'], (0, locale_1.t)('redundant_quotes'));
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
if (checks['double_not'] !== 'off') {
|
|
172
|
+
visitor.on('not', (node) => {
|
|
173
|
+
if (node.children &&
|
|
174
|
+
node.children.length >= 2 &&
|
|
175
|
+
node.children[1].type === 'list' &&
|
|
176
|
+
node.children[1].children &&
|
|
177
|
+
node.children[1].children.length > 0 &&
|
|
178
|
+
node.children[1].children[0].type === 'symbol' &&
|
|
179
|
+
node.children[1].children[0].name === 'not') {
|
|
180
|
+
addIssue('double_not', node.pos.line, checks['double_not'], (0, locale_1.t)('double_not'));
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
if (checks['misplaced_else'] !== 'off') {
|
|
185
|
+
visitor.on('if', (node) => {
|
|
186
|
+
if (node.children && node.children.length === 4) {
|
|
187
|
+
const cond = node.children[1];
|
|
188
|
+
if (cond.type === 'list' &&
|
|
189
|
+
cond.children &&
|
|
190
|
+
cond.children.length >= 2 &&
|
|
191
|
+
cond.children[0].type === 'symbol' &&
|
|
192
|
+
cond.children[0].name === 'not') {
|
|
193
|
+
const innerName = cond.children[1].name || '';
|
|
194
|
+
addIssue('misplaced_else', node.pos.line, checks['misplaced_else'], (0, locale_1.t)('misplaced_else', innerName));
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
if (checks['quote_vs_function'] !== 'off') {
|
|
200
|
+
const higherOrder = new Set([
|
|
201
|
+
'mapcar',
|
|
202
|
+
'apply',
|
|
203
|
+
'lambda',
|
|
204
|
+
'vl-sort',
|
|
205
|
+
'vl-sort-i',
|
|
206
|
+
'vl-remove-if',
|
|
207
|
+
'vl-remove-if-not',
|
|
208
|
+
'vl-member-if',
|
|
209
|
+
'vl-some',
|
|
210
|
+
'vl-every',
|
|
211
|
+
]);
|
|
212
|
+
visitor.on('quote', (node) => {
|
|
213
|
+
if (node.children &&
|
|
214
|
+
node.children.length >= 2 &&
|
|
215
|
+
node.children[1].type === 'list' &&
|
|
216
|
+
node.children[1].children &&
|
|
217
|
+
node.children[1].children.length > 0 &&
|
|
218
|
+
node.children[1].children[0].type === 'symbol' &&
|
|
219
|
+
node.children[1].children[0].name === 'lambda') {
|
|
220
|
+
const parent = node.parent;
|
|
221
|
+
if (parent && parent.children && parent.children.length > 0) {
|
|
222
|
+
const pName = (parent.children[0].type === 'symbol' && parent.children[0].name) || '';
|
|
223
|
+
if (higherOrder.has(pName)) {
|
|
224
|
+
addIssue('quote_vs_function', node.pos.line, checks['quote_vs_function'], (0, locale_1.t)('quote_vs_function', pName));
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
visitor.run(ast);
|
|
231
|
+
return issues;
|
|
232
|
+
}
|
|
233
|
+
function lintFiles(files, config, rootDir) {
|
|
70
234
|
(0, locale_1.setLocale)(config.locale || 'zh');
|
|
71
235
|
const allIssues = [];
|
|
72
|
-
const
|
|
73
|
-
const useCache = options?.useCache ?? false;
|
|
74
|
-
for (let idx = 0; idx < files.length; idx++) {
|
|
75
|
-
const filepath = files[idx];
|
|
236
|
+
for (const filepath of files) {
|
|
76
237
|
const relPath = path.relative(rootDir, filepath);
|
|
77
|
-
// Check ignore patterns
|
|
78
|
-
const relForward = relPath.replace(/\\/g, '/');
|
|
79
|
-
if (ignorePatterns.some(re => re.test(relForward)))
|
|
80
|
-
continue;
|
|
81
|
-
// Check cache
|
|
82
|
-
if (useCache && (0, cache_1.isCached)(filepath, rootDir))
|
|
83
|
-
continue;
|
|
84
|
-
options?.onProgress?.(idx + 1, files.length);
|
|
85
238
|
let content;
|
|
86
239
|
try {
|
|
87
240
|
content = fs.readFileSync(filepath, 'utf-8');
|
|
88
241
|
}
|
|
89
242
|
catch {
|
|
90
243
|
allIssues.push({
|
|
91
|
-
file: relPath,
|
|
244
|
+
file: relPath,
|
|
245
|
+
line: 1,
|
|
246
|
+
severity: 'error',
|
|
247
|
+
rule: 'read',
|
|
92
248
|
message: (0, locale_1.t)('runner.read_error'),
|
|
93
249
|
});
|
|
94
250
|
continue;
|
|
@@ -96,61 +252,63 @@ function lintFiles(files, config, rootDir, options) {
|
|
|
96
252
|
// Per-directory config override
|
|
97
253
|
const override = (0, config_1.findOverrides)(filepath);
|
|
98
254
|
const effectiveConfig = override ? (0, config_1.mergeOverrides)(config, override) : config;
|
|
99
|
-
|
|
100
|
-
// Mark as cached if no issues found
|
|
101
|
-
if (useCache && fileIssues.length === 0) {
|
|
102
|
-
(0, cache_1.markCached)(filepath, rootDir);
|
|
103
|
-
}
|
|
104
|
-
allIssues.push(...fileIssues);
|
|
255
|
+
allIssues.push(...runChecks(content, relPath, effectiveConfig));
|
|
105
256
|
}
|
|
106
257
|
return allIssues;
|
|
107
258
|
}
|
|
108
|
-
function lintFilesParallel(files, config, rootDir
|
|
259
|
+
function lintFilesParallel(files, config, rootDir) {
|
|
109
260
|
(0, locale_1.setLocale)(config.locale || 'zh');
|
|
110
|
-
const ignorePatterns = options?.ignorePatterns || [];
|
|
111
261
|
return new Promise((resolve) => {
|
|
112
262
|
const allIssues = [];
|
|
113
263
|
let completed = 0;
|
|
114
264
|
const maxWorkers = Math.min(os.cpus().length, files.length);
|
|
115
265
|
let nextIndex = 0;
|
|
116
266
|
function startWorker() {
|
|
117
|
-
if (nextIndex >= files.length)
|
|
118
|
-
if (completed >= files.length)
|
|
119
|
-
resolve(allIssues);
|
|
267
|
+
if (nextIndex >= files.length)
|
|
120
268
|
return;
|
|
121
|
-
}
|
|
122
269
|
const idx = nextIndex++;
|
|
123
270
|
const filepath = files[idx];
|
|
124
271
|
const relPath = path.relative(rootDir, filepath);
|
|
125
|
-
// Check ignore patterns
|
|
126
|
-
const relForward = relPath.replace(/\\/g, '/');
|
|
127
|
-
if (ignorePatterns.some(re => re.test(relForward))) {
|
|
128
|
-
completed++;
|
|
129
|
-
startWorker();
|
|
130
|
-
if (completed >= files.length)
|
|
131
|
-
resolve(allIssues);
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
272
|
const worker = new worker_threads_1.Worker(path.join(__dirname, 'worker.js'), {
|
|
135
273
|
workerData: { filepath, relPath, config },
|
|
136
|
-
eval: false,
|
|
137
274
|
});
|
|
138
275
|
worker.on('message', (msg) => {
|
|
139
276
|
allIssues.push(...msg.issues);
|
|
140
277
|
completed++;
|
|
141
|
-
options?.onProgress?.(completed, files.length);
|
|
142
278
|
worker.terminate();
|
|
143
279
|
startWorker();
|
|
144
280
|
if (completed >= files.length)
|
|
145
281
|
resolve(allIssues);
|
|
146
282
|
});
|
|
147
|
-
worker.on('error', () => {
|
|
283
|
+
worker.on('error', (err) => {
|
|
284
|
+
allIssues.push({
|
|
285
|
+
file: relPath,
|
|
286
|
+
line: 1,
|
|
287
|
+
severity: 'error',
|
|
288
|
+
rule: 'worker',
|
|
289
|
+
message: err.message,
|
|
290
|
+
});
|
|
148
291
|
completed++;
|
|
149
292
|
worker.terminate();
|
|
150
293
|
startWorker();
|
|
151
294
|
if (completed >= files.length)
|
|
152
295
|
resolve(allIssues);
|
|
153
296
|
});
|
|
297
|
+
worker.on('exit', (code) => {
|
|
298
|
+
if (code !== 0) {
|
|
299
|
+
allIssues.push({
|
|
300
|
+
file: relPath,
|
|
301
|
+
line: 1,
|
|
302
|
+
severity: 'error',
|
|
303
|
+
rule: 'worker',
|
|
304
|
+
message: `Worker exited with code ${code}`,
|
|
305
|
+
});
|
|
306
|
+
completed++;
|
|
307
|
+
startWorker();
|
|
308
|
+
if (completed >= files.length)
|
|
309
|
+
resolve(allIssues);
|
|
310
|
+
}
|
|
311
|
+
});
|
|
154
312
|
}
|
|
155
313
|
for (let i = 0; i < maxWorkers; i++) {
|
|
156
314
|
startWorker();
|
|
@@ -159,34 +317,65 @@ function lintFilesParallel(files, config, rootDir, options) {
|
|
|
159
317
|
resolve([]);
|
|
160
318
|
});
|
|
161
319
|
}
|
|
320
|
+
const UTF8_BOM = 0xfeff;
|
|
162
321
|
function fixFile(filepath) {
|
|
163
322
|
const fixes = [];
|
|
164
323
|
let content = fs.readFileSync(filepath, 'utf-8');
|
|
165
324
|
// Fix trailing whitespace
|
|
166
|
-
const wsFixed = content
|
|
325
|
+
const wsFixed = content
|
|
326
|
+
.split('\n')
|
|
327
|
+
.map((l) => l.replace(/[ \t]+$/, ''))
|
|
328
|
+
.join('\n');
|
|
167
329
|
if (wsFixed !== content) {
|
|
168
330
|
content = wsFixed;
|
|
169
331
|
fixes.push('trailing_whitespace');
|
|
170
332
|
}
|
|
171
333
|
// Fix UTF-8 BOM
|
|
172
|
-
if (content.charCodeAt(0) ===
|
|
334
|
+
if (content.charCodeAt(0) === UTF8_BOM) {
|
|
173
335
|
content = content.slice(1);
|
|
174
336
|
fixes.push('encoding (BOM)');
|
|
175
337
|
}
|
|
176
|
-
// Fix
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
338
|
+
// Fix trailing parens: remove excess ')' from end of content
|
|
339
|
+
let openCount = 0;
|
|
340
|
+
let closeCount = 0;
|
|
341
|
+
let fixContent = content;
|
|
342
|
+
for (let i = 0; i < fixContent.length; i++) {
|
|
343
|
+
const ch = fixContent[i];
|
|
344
|
+
if (ch === '(')
|
|
345
|
+
openCount++;
|
|
346
|
+
else if (ch === ')')
|
|
347
|
+
closeCount++;
|
|
348
|
+
}
|
|
349
|
+
if (closeCount > openCount) {
|
|
350
|
+
let excess = closeCount - openCount;
|
|
351
|
+
while (excess > 0 && fixContent.endsWith(')')) {
|
|
352
|
+
fixContent = fixContent.slice(0, -1);
|
|
353
|
+
excess--;
|
|
354
|
+
}
|
|
355
|
+
// Also trim trailing whitespace after removing parens
|
|
356
|
+
fixContent = fixContent.replace(/\n[ \t]*$/, '');
|
|
357
|
+
if (fixContent !== content) {
|
|
358
|
+
content = fixContent;
|
|
359
|
+
fixes.push('trailing_paren');
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
// Fix empty comments: remove lines that are only ';' with optional whitespace
|
|
363
|
+
const lines = content.split('\n');
|
|
364
|
+
let changed = false;
|
|
365
|
+
const fixedLines = lines.map((l) => {
|
|
366
|
+
if (/^\s*;\s*$/.test(l)) {
|
|
367
|
+
changed = true;
|
|
368
|
+
return '';
|
|
369
|
+
}
|
|
370
|
+
return l;
|
|
371
|
+
});
|
|
372
|
+
if (changed) {
|
|
373
|
+
content = fixedLines.join('\n');
|
|
374
|
+
fixes.push('empty_comment');
|
|
183
375
|
}
|
|
184
376
|
if (fixes.length > 0) {
|
|
185
377
|
fs.writeFileSync(filepath, content, 'utf-8');
|
|
186
378
|
}
|
|
187
379
|
return fixes;
|
|
188
380
|
}
|
|
189
|
-
function clearCache(rootDir) {
|
|
190
|
-
(0, cache_1.clearCache)(rootDir);
|
|
191
|
-
}
|
|
192
381
|
//# sourceMappingURL=runner.js.map
|
package/dist/sbcl.js
CHANGED
|
@@ -60,22 +60,26 @@ function runSbclLint(srcDir, sbclConfig, stubPackagesPath) {
|
|
|
60
60
|
// Locate lint-sbcl.lisp bundled with the package
|
|
61
61
|
const scriptPath = path.join(__dirname, '..', 'lib', 'lint-sbcl.lisp');
|
|
62
62
|
if (!fs.existsSync(scriptPath)) {
|
|
63
|
-
return [
|
|
64
|
-
|
|
63
|
+
return [
|
|
64
|
+
{
|
|
65
|
+
file: 'internal',
|
|
66
|
+
line: 1,
|
|
67
|
+
severity: 'error',
|
|
68
|
+
rule: 'sbcl',
|
|
65
69
|
message: (0, locale_1.t)('sbcl.script_not_found', scriptPath),
|
|
66
|
-
}
|
|
70
|
+
},
|
|
71
|
+
];
|
|
67
72
|
}
|
|
68
73
|
try {
|
|
69
74
|
// Convert arrays to Lisp-readable format: ("a" "b")
|
|
70
|
-
const toLispList = (arr) => '(' + arr.map(s => `"${s}"`).join(' ') + ')';
|
|
71
|
-
const locale = (0, locale_1.getLocale)();
|
|
75
|
+
const toLispList = (arr) => '(' + arr.map((s) => `"${s}"`).join(' ') + ')';
|
|
72
76
|
const result = (0, child_process_1.execFileSync)(sbcl, [
|
|
73
|
-
'--script',
|
|
77
|
+
'--script',
|
|
78
|
+
scriptPath,
|
|
74
79
|
srcDir,
|
|
75
80
|
stubPackagesPath,
|
|
76
81
|
toLispList(sbclConfig.walk_exclude),
|
|
77
82
|
toLispList(sbclConfig.defmacro_allow_files),
|
|
78
|
-
locale,
|
|
79
83
|
], {
|
|
80
84
|
encoding: 'utf-8',
|
|
81
85
|
maxBuffer: 50 * 1024 * 1024,
|
|
@@ -111,9 +115,7 @@ function parseSbclOutput(output, srcDir) {
|
|
|
111
115
|
const severity = sev === 'ERROR' ? 'error' : 'warn';
|
|
112
116
|
const lineno = lineStr ? parseInt(lineStr, 10) : 1;
|
|
113
117
|
// Resolve relative path against srcDir
|
|
114
|
-
const resolved = filePath.includes(':')
|
|
115
|
-
? filePath
|
|
116
|
-
: filePath.replace(/\\/g, '/');
|
|
118
|
+
const resolved = filePath.includes(':') ? filePath : filePath.replace(/\\/g, '/');
|
|
117
119
|
issues.push({
|
|
118
120
|
file: resolved,
|
|
119
121
|
line: lineno,
|
|
@@ -128,7 +130,10 @@ function parseSbclOutput(output, srcDir) {
|
|
|
128
130
|
if (sev) {
|
|
129
131
|
const msg = trimmed.replace(/^\[(ERROR|WARN|NOTE)\]\s*/, '');
|
|
130
132
|
issues.push({
|
|
131
|
-
file: srcDir,
|
|
133
|
+
file: srcDir,
|
|
134
|
+
line: 1,
|
|
135
|
+
severity: sev,
|
|
136
|
+
rule: 'sbcl',
|
|
132
137
|
message: msg,
|
|
133
138
|
});
|
|
134
139
|
}
|
package/dist/worker.js
CHANGED
|
@@ -3,23 +3,28 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const worker_threads_1 = require("worker_threads");
|
|
4
4
|
const fs_1 = require("fs");
|
|
5
5
|
const locale_1 = require("./locale");
|
|
6
|
-
const
|
|
6
|
+
const runner_1 = require("./runner");
|
|
7
7
|
if (worker_threads_1.parentPort && worker_threads_1.workerData) {
|
|
8
8
|
const input = worker_threads_1.workerData;
|
|
9
9
|
(0, locale_1.setLocale)(input.config.locale || 'zh');
|
|
10
10
|
try {
|
|
11
11
|
const content = (0, fs_1.readFileSync)(input.filepath, 'utf-8');
|
|
12
|
-
const issues = (0,
|
|
12
|
+
const issues = (0, runner_1.runChecks)(content, input.relPath, input.config);
|
|
13
13
|
const output = { filepath: input.filepath, issues };
|
|
14
14
|
worker_threads_1.parentPort.postMessage(output);
|
|
15
15
|
}
|
|
16
16
|
catch {
|
|
17
17
|
const output = {
|
|
18
18
|
filepath: input.filepath,
|
|
19
|
-
issues: [
|
|
20
|
-
|
|
19
|
+
issues: [
|
|
20
|
+
{
|
|
21
|
+
file: input.relPath,
|
|
22
|
+
line: 1,
|
|
23
|
+
severity: 'error',
|
|
24
|
+
rule: 'read',
|
|
21
25
|
message: 'Cannot read file',
|
|
22
|
-
}
|
|
26
|
+
},
|
|
27
|
+
],
|
|
23
28
|
};
|
|
24
29
|
worker_threads_1.parentPort.postMessage(output);
|
|
25
30
|
}
|
package/lib/lint-sbcl.lisp
CHANGED
|
@@ -1,49 +1,14 @@
|
|
|
1
1
|
;; @lisp SBCL Lint — syntax validation via SBCL
|
|
2
|
-
;; Usage: sbcl --script lint-sbcl.lisp <src-dir> <stub-packages.json> <walk-exclude-json> <defmacro-allow-files-json>
|
|
2
|
+
;; Usage: sbcl --script lint-sbcl.lisp <src-dir> <stub-packages.json> <walk-exclude-json> <defmacro-allow-files-json>
|
|
3
3
|
|
|
4
4
|
(require :uiop)
|
|
5
5
|
|
|
6
6
|
(defparameter *errors* 0)
|
|
7
7
|
(defparameter *warnings* 0)
|
|
8
8
|
(defparameter *checked* 0)
|
|
9
|
-
(defparameter *locale* "zh")
|
|
10
|
-
|
|
11
|
-
;; ── i18n ──────────────────────────────────────────────────────────────
|
|
12
|
-
(defun i18n (key)
|
|
13
|
-
(cdr (assoc key
|
|
14
|
-
(if (string= *locale* "zh")
|
|
15
|
-
'((:not-found . "not found symbol")
|
|
16
|
-
(:syntax-error . "syntax error")
|
|
17
|
-
(:vec-syntax . "#( vector syntax")
|
|
18
|
-
(:char-syntax . "# backslash char literal")
|
|
19
|
-
(:eval-syntax . "#. read-time eval")
|
|
20
|
-
(:defmacro . "defmacro")
|
|
21
|
-
(:trailing-ws . "trailing whitespace")
|
|
22
|
-
(:ok . "OK")
|
|
23
|
-
(:fail . "FAIL")
|
|
24
|
-
(:header . " @lisp SBCL Lint")
|
|
25
|
-
(:source . " Source")
|
|
26
|
-
(:found . " Found ~d .lsp files")
|
|
27
|
-
(:scanned . " Scanned")
|
|
28
|
-
(:errors . " Errors")
|
|
29
|
-
(:warnings . " Warnings"))
|
|
30
|
-
'((:not-found . "not found symbol")
|
|
31
|
-
(:syntax-error . "syntax error")
|
|
32
|
-
(:vec-syntax . "#( vector syntax")
|
|
33
|
-
(:char-syntax . "# backslash char literal")
|
|
34
|
-
(:eval-syntax . "#. read-time eval")
|
|
35
|
-
(:defmacro . "defmacro")
|
|
36
|
-
(:trailing-ws . "trailing whitespace")
|
|
37
|
-
(:ok . "OK")
|
|
38
|
-
(:fail . "FAIL")
|
|
39
|
-
(:header . " @lisp SBCL Lint")
|
|
40
|
-
(:source . " Source")
|
|
41
|
-
(:found . " Found ~d .lsp files")
|
|
42
|
-
(:scanned . " Scanned")
|
|
43
|
-
(:errors . " Errors")
|
|
44
|
-
(:warnings . " Warnings"))))))
|
|
45
9
|
|
|
46
10
|
;; ── Stub packages from external file ──────────────────────────────────
|
|
11
|
+
;; File format: alist ((name use*) ...) — valid Lisp data
|
|
47
12
|
(defun load-stub-packages (file-path)
|
|
48
13
|
(flet ((ensure-pkg (name &optional use-list)
|
|
49
14
|
(unless (find-package name)
|
|
@@ -87,10 +52,11 @@
|
|
|
87
52
|
(let ((msg (princ-to-string e)))
|
|
88
53
|
(cond
|
|
89
54
|
((search "not found" msg)
|
|
90
|
-
(format t "~% [NOTE] ~a: ~a~%" rel
|
|
55
|
+
(format t "~% [NOTE] ~a: ~a~%" rel
|
|
56
|
+
(subseq msg 0 (min 80 (length msg))))
|
|
91
57
|
(incf *warnings*))
|
|
92
58
|
(t
|
|
93
|
-
(format t "
|
|
59
|
+
(format t "FAIL~% [ERROR] ~a: ~a~%" rel e)
|
|
94
60
|
(incf *errors*)
|
|
95
61
|
(return-from check-file))))))
|
|
96
62
|
;; Trailing whitespace
|
|
@@ -101,7 +67,7 @@
|
|
|
101
67
|
when (and (> (length line) 0)
|
|
102
68
|
(find (char line (1- (length line))) '(#\Space #\Tab)))
|
|
103
69
|
do (progn
|
|
104
|
-
(format t "~% [WARN] ~a line ~d:
|
|
70
|
+
(format t "~% [WARN] ~a line ~d: trailing whitespace~%" rel lineno)
|
|
105
71
|
(incf *warnings*))))
|
|
106
72
|
;; CL-ism checks: raw content scan
|
|
107
73
|
(with-open-file (s path :direction :input)
|
|
@@ -109,19 +75,19 @@
|
|
|
109
75
|
(file-position s 0)
|
|
110
76
|
(read-sequence content s)
|
|
111
77
|
(when (search "#(" content)
|
|
112
|
-
(format t "~% [WARN] ~a:
|
|
78
|
+
(format t "~% [WARN] ~a: #( vector syntax (not valid in AutoLISP)~%" rel)
|
|
113
79
|
(incf *warnings*))
|
|
114
80
|
(when (search "#\\" content)
|
|
115
|
-
(format t "~% [WARN] ~a:
|
|
81
|
+
(format t "~% [WARN] ~a: #\\ character literal syntax (not valid in AutoLISP)~%" rel)
|
|
116
82
|
(incf *warnings*))
|
|
117
83
|
(when (search "#." content)
|
|
118
|
-
(format t "~% [WARN] ~a:
|
|
84
|
+
(format t "~% [WARN] ~a: #. read-time eval syntax (not valid in AutoLISP)~%" rel)
|
|
119
85
|
(incf *warnings*))
|
|
120
86
|
(when (and (search "defmacro" content)
|
|
121
87
|
(not (some (lambda (s) (search s fullname)) defmacro-allow-files)))
|
|
122
|
-
(format t "~% [WARN] ~a:
|
|
88
|
+
(format t "~% [WARN] ~a: defmacro (not valid in AutoLISP)~%" rel)
|
|
123
89
|
(incf *warnings*))))
|
|
124
|
-
(format t "
|
|
90
|
+
(format t "OK~%")))
|
|
125
91
|
|
|
126
92
|
;; ── Main ──────────────────────────────────────────────────────────────
|
|
127
93
|
(defun main ()
|
|
@@ -133,26 +99,25 @@
|
|
|
133
99
|
'(".vscode" "test" "experiment" "tools" ".git")))
|
|
134
100
|
(defmacro-allow (if (fourth args)
|
|
135
101
|
(read-from-string (fourth args))
|
|
136
|
-
'("compat-cl")))
|
|
137
|
-
|
|
138
|
-
(when locale (setf *locale* locale))
|
|
102
|
+
'("compat-cl"))))
|
|
103
|
+
;; Load stub packages for CAD runtime symbols
|
|
139
104
|
(load-stub-packages stub-file)
|
|
140
105
|
|
|
141
106
|
(format t "~%==================================================~%")
|
|
142
|
-
(format t "
|
|
143
|
-
(format t "
|
|
107
|
+
(format t " @lisp SBCL Lint~%")
|
|
108
|
+
(format t " Source: ~a~%" (namestring (pathname src-dir)))
|
|
144
109
|
(format t "==================================================~%~%")
|
|
145
110
|
(setf *errors* 0 *warnings* 0 *checked* 0)
|
|
146
111
|
|
|
147
112
|
(let ((files (walk-tree src-dir walk-exclude)))
|
|
148
|
-
(format t "~
|
|
113
|
+
(format t " Found ~d .lsp files~%~%" (length files))
|
|
149
114
|
(dolist (f files)
|
|
150
115
|
(check-file f src-dir defmacro-allow)))
|
|
151
116
|
|
|
152
117
|
(format t "~%==================================================~%")
|
|
153
|
-
(format t "
|
|
154
|
-
(format t "
|
|
155
|
-
(format t "
|
|
118
|
+
(format t " Scanned: ~d files~%" *checked*)
|
|
119
|
+
(format t " Errors: ~d~%" *errors*)
|
|
120
|
+
(format t " Warnings: ~d~%" *warnings*)
|
|
156
121
|
(format t "==================================================~%~%")
|
|
157
122
|
(if (> *errors* 0)
|
|
158
123
|
(uiop:quit 1)
|