@atlisp/lint 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/atlisp-lint.default.json +6 -0
  2. package/dist/atlisp-lint.default.json +6 -0
  3. package/dist/checks/arg-count.d.ts +3 -0
  4. package/dist/checks/arg-count.d.ts.map +1 -0
  5. package/dist/checks/arg-count.js +120 -0
  6. package/dist/checks/arg-count.js.map +1 -0
  7. package/dist/checks/cond-simplify.d.ts +3 -0
  8. package/dist/checks/cond-simplify.d.ts.map +1 -0
  9. package/dist/checks/cond-simplify.js +42 -0
  10. package/dist/checks/cond-simplify.js.map +1 -0
  11. package/dist/checks/dangerous-calls.d.ts.map +1 -1
  12. package/dist/checks/dangerous-calls.js +9 -7
  13. package/dist/checks/dangerous-calls.js.map +1 -1
  14. package/dist/checks/error-handling.d.ts +3 -0
  15. package/dist/checks/error-handling.d.ts.map +1 -0
  16. package/dist/checks/error-handling.js +53 -0
  17. package/dist/checks/error-handling.js.map +1 -0
  18. package/dist/checks/extra-parens.d.ts +3 -0
  19. package/dist/checks/extra-parens.d.ts.map +1 -0
  20. package/dist/checks/extra-parens.js +42 -0
  21. package/dist/checks/extra-parens.js.map +1 -0
  22. package/dist/checks/global-naming.d.ts +3 -0
  23. package/dist/checks/global-naming.d.ts.map +1 -0
  24. package/dist/checks/global-naming.js +51 -0
  25. package/dist/checks/global-naming.js.map +1 -0
  26. package/dist/checks/missing-doc.js +1 -1
  27. package/dist/checks/missing-doc.js.map +1 -1
  28. package/dist/checks/parameter-naming.d.ts.map +1 -1
  29. package/dist/checks/parameter-naming.js +4 -1
  30. package/dist/checks/parameter-naming.js.map +1 -1
  31. package/dist/checks/strcat-usage.d.ts +3 -0
  32. package/dist/checks/strcat-usage.d.ts.map +1 -0
  33. package/dist/checks/strcat-usage.js +22 -0
  34. package/dist/checks/strcat-usage.js.map +1 -0
  35. package/dist/config.d.ts.map +1 -1
  36. package/dist/config.js +6 -0
  37. package/dist/config.js.map +1 -1
  38. package/dist/formatters.d.ts +1 -0
  39. package/dist/formatters.d.ts.map +1 -1
  40. package/dist/formatters.js +55 -0
  41. package/dist/formatters.js.map +1 -1
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/index.js +58 -2
  44. package/dist/index.js.map +1 -1
  45. package/dist/lib/lint-sbcl.lisp +54 -19
  46. package/dist/locale.d.ts.map +1 -1
  47. package/dist/locale.js +20 -0
  48. package/dist/locale.js.map +1 -1
  49. package/dist/rules.d.ts +9 -0
  50. package/dist/rules.d.ts.map +1 -0
  51. package/dist/rules.js +39 -0
  52. package/dist/rules.js.map +1 -0
  53. package/dist/runner.d.ts.map +1 -1
  54. package/dist/runner.js +12 -0
  55. package/dist/runner.js.map +1 -1
  56. package/dist/sbcl.d.ts.map +1 -1
  57. package/dist/sbcl.js +2 -0
  58. package/dist/sbcl.js.map +1 -1
  59. package/dist/validate.d.ts +8 -0
  60. package/dist/validate.d.ts.map +1 -0
  61. package/dist/validate.js +55 -0
  62. package/dist/validate.js.map +1 -0
  63. package/dist/watch.d.ts +9 -0
  64. package/dist/watch.d.ts.map +1 -0
  65. package/dist/watch.js +109 -0
  66. package/dist/watch.js.map +1 -0
  67. package/lib/lint-sbcl.lisp +54 -19
  68. package/package.json +1 -1
@@ -0,0 +1,8 @@
1
+ import { LintConfig } from './types';
2
+ interface ValidationError {
3
+ path: string;
4
+ message: string;
5
+ }
6
+ export declare function validateConfig(config: LintConfig): ValidationError[];
7
+ export {};
8
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAY,MAAM,SAAS,CAAC;AAc/C,UAAU,eAAe;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,eAAe,EAAE,CA8CpE"}
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateConfig = validateConfig;
4
+ const VALID_RULES = [
5
+ 'parens', 'encoding', 'cl_syntax', 'quit_exit', 'command_shell',
6
+ 'startapp', 'vl_registry_write', 'vlax_without_loading', 'token_in_url',
7
+ 'open_without_close', 'bare_function_names', 'line_length',
8
+ 'function_complexity', 'parameter_naming', 'unused_variable', 'missing_doc',
9
+ 'error_handling', 'global_naming', 'extra_parens', 'arg_count',
10
+ 'strcat_usage', 'cond_simplify', 'trailing_whitespace',
11
+ 'module_registration', 'namespace_header',
12
+ ];
13
+ const VALID_SEVERITIES = ['off', 'warn', 'error'];
14
+ function validateConfig(config) {
15
+ const errors = [];
16
+ if (config.locale && config.locale !== 'zh' && config.locale !== 'en') {
17
+ errors.push({ path: 'locale', message: `Invalid locale '${config.locale}', expected 'zh' or 'en'` });
18
+ }
19
+ if (config.checks) {
20
+ for (const [rule, sev] of Object.entries(config.checks)) {
21
+ if (!VALID_RULES.includes(rule)) {
22
+ errors.push({ path: `checks.${rule}`, message: `Unknown rule '${rule}'` });
23
+ }
24
+ if (!VALID_SEVERITIES.includes(sev)) {
25
+ errors.push({ path: `checks.${rule}`, message: `Invalid severity '${sev}', expected 'off', 'warn', or 'error'` });
26
+ }
27
+ }
28
+ }
29
+ if (config.source) {
30
+ if (!Array.isArray(config.source.globs)) {
31
+ errors.push({ path: 'source.globs', message: 'Must be an array of glob patterns' });
32
+ }
33
+ if (!Array.isArray(config.source.exclude)) {
34
+ errors.push({ path: 'source.exclude', message: 'Must be an array of glob patterns' });
35
+ }
36
+ }
37
+ if (config.line_length) {
38
+ if (typeof config.line_length.max !== 'number' || config.line_length.max < 1) {
39
+ errors.push({ path: 'line_length.max', message: 'Must be a positive number' });
40
+ }
41
+ if (typeof config.line_length.tab_width !== 'number' || config.line_length.tab_width < 1) {
42
+ errors.push({ path: 'line_length.tab_width', message: 'Must be a positive number' });
43
+ }
44
+ }
45
+ if (config.function_complexity) {
46
+ if (typeof config.function_complexity.max_lines !== 'number' || config.function_complexity.max_lines < 1) {
47
+ errors.push({ path: 'function_complexity.max_lines', message: 'Must be a positive number' });
48
+ }
49
+ if (typeof config.function_complexity.max_nesting !== 'number' || config.function_complexity.max_nesting < 1) {
50
+ errors.push({ path: 'function_complexity.max_nesting', message: 'Must be a positive number' });
51
+ }
52
+ }
53
+ return errors;
54
+ }
55
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { LintConfig } from './types';
2
+ interface WatchOptions {
3
+ rootDir: string;
4
+ format: 'default' | 'json';
5
+ config: LintConfig;
6
+ }
7
+ export declare function watchFiles(files: string[], options: WatchOptions): void;
8
+ export {};
9
+ //# sourceMappingURL=watch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../src/watch.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAS,MAAM,SAAS,CAAC;AAM5C,UAAU,YAAY;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,SAAS,GAAG,MAAM,CAAC;IAC3B,MAAM,EAAE,UAAU,CAAC;CACpB;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI,CA4CvE"}
package/dist/watch.js ADDED
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.watchFiles = watchFiles;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const runner_1 = require("./runner");
40
+ const formatters_1 = require("./formatters");
41
+ const locale_1 = require("./locale");
42
+ function watchFiles(files, options) {
43
+ const { rootDir, format, config } = options;
44
+ (0, locale_1.setLocale)(config.locale || 'zh');
45
+ // Initial lint
46
+ runLint(files, rootDir, format, config);
47
+ // Watch all files for changes
48
+ const watchers = [];
49
+ const watchedDirs = new Set();
50
+ for (const f of files) {
51
+ const dir = path.dirname(f);
52
+ if (!watchedDirs.has(dir)) {
53
+ watchedDirs.add(dir);
54
+ try {
55
+ const watcher = fs.watch(dir, (eventType, filename) => {
56
+ if (!filename)
57
+ return;
58
+ const fullPath = path.join(dir, filename);
59
+ if (files.includes(fullPath)) {
60
+ // Debounce: wait a bit for the file to finish writing
61
+ setTimeout(() => {
62
+ runLint(files, rootDir, format, config);
63
+ }, 200);
64
+ }
65
+ });
66
+ watchers.push(watcher);
67
+ }
68
+ catch { /* ignore */ }
69
+ }
70
+ }
71
+ console.log(`\n${(0, locale_1.t)('index.watching')} (${files.length} files)`);
72
+ console.log((0, locale_1.t)('index.watch_hint'));
73
+ // Cleanup on exit
74
+ process.on('SIGINT', () => {
75
+ for (const w of watchers)
76
+ w.close();
77
+ process.exit(0);
78
+ });
79
+ process.on('SIGTERM', () => {
80
+ for (const w of watchers)
81
+ w.close();
82
+ process.exit(0);
83
+ });
84
+ }
85
+ function runLint(files, rootDir, format, config) {
86
+ // Clear console
87
+ process.stdout.write('\x1Bc');
88
+ const issues = (0, runner_1.lintFiles)(files, config, rootDir);
89
+ const fileContents = new Map();
90
+ for (const iss of issues) {
91
+ if (!fileContents.has(iss.file)) {
92
+ const fp = path.resolve(rootDir, iss.file);
93
+ try {
94
+ fileContents.set(iss.file, fs.readFileSync(fp, 'utf-8'));
95
+ }
96
+ catch { /* ignore */ }
97
+ }
98
+ }
99
+ if (format === 'json') {
100
+ console.log((0, formatters_1.formatJson)(issues));
101
+ }
102
+ else {
103
+ console.log((0, formatters_1.formatDefault)(issues, fileContents));
104
+ }
105
+ const errorCount = issues.filter(i => i.severity === 'error').length;
106
+ const warningCount = issues.filter(i => i.severity === 'warn').length;
107
+ console.log(`\n[${new Date().toLocaleTimeString()}] ${(0, locale_1.t)('index.watch_status', files.length, errorCount, warningCount)}`);
108
+ }
109
+ //# sourceMappingURL=watch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watch.js","sourceRoot":"","sources":["../src/watch.ts"],"names":[],"mappings":"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"}
@@ -1,14 +1,49 @@
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> <locale>
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"))))))
9
45
 
10
46
  ;; ── Stub packages from external file ──────────────────────────────────
11
- ;; File format: alist ((name use*) ...) — valid Lisp data
12
47
  (defun load-stub-packages (file-path)
13
48
  (flet ((ensure-pkg (name &optional use-list)
14
49
  (unless (find-package name)
@@ -52,11 +87,10 @@
52
87
  (let ((msg (princ-to-string e)))
53
88
  (cond
54
89
  ((search "not found" msg)
55
- (format t "~% [NOTE] ~a: ~a~%" rel
56
- (subseq msg 0 (min 80 (length msg))))
90
+ (format t "~% [NOTE] ~a: ~a~%" rel (i18n :not-found))
57
91
  (incf *warnings*))
58
92
  (t
59
- (format t "FAIL~% [ERROR] ~a: ~a~%" rel e)
93
+ (format t "~a~% [ERROR] ~a: ~a~%" (i18n :fail) rel (i18n :syntax-error))
60
94
  (incf *errors*)
61
95
  (return-from check-file))))))
62
96
  ;; Trailing whitespace
@@ -67,7 +101,7 @@
67
101
  when (and (> (length line) 0)
68
102
  (find (char line (1- (length line))) '(#\Space #\Tab)))
69
103
  do (progn
70
- (format t "~% [WARN] ~a line ~d: trailing whitespace~%" rel lineno)
104
+ (format t "~% [WARN] ~a line ~d: ~a~%" rel lineno (i18n :trailing-ws))
71
105
  (incf *warnings*))))
72
106
  ;; CL-ism checks: raw content scan
73
107
  (with-open-file (s path :direction :input)
@@ -75,19 +109,19 @@
75
109
  (file-position s 0)
76
110
  (read-sequence content s)
77
111
  (when (search "#(" content)
78
- (format t "~% [WARN] ~a: #( vector syntax (not valid in AutoLISP)~%" rel)
112
+ (format t "~% [WARN] ~a: ~a~%" rel (i18n :vec-syntax))
79
113
  (incf *warnings*))
80
114
  (when (search "#\\" content)
81
- (format t "~% [WARN] ~a: #\\ character literal syntax (not valid in AutoLISP)~%" rel)
115
+ (format t "~% [WARN] ~a: ~a~%" rel (i18n :char-syntax))
82
116
  (incf *warnings*))
83
117
  (when (search "#." content)
84
- (format t "~% [WARN] ~a: #. read-time eval syntax (not valid in AutoLISP)~%" rel)
118
+ (format t "~% [WARN] ~a: ~a~%" rel (i18n :eval-syntax))
85
119
  (incf *warnings*))
86
120
  (when (and (search "defmacro" content)
87
121
  (not (some (lambda (s) (search s fullname)) defmacro-allow-files)))
88
- (format t "~% [WARN] ~a: defmacro (not valid in AutoLISP)~%" rel)
122
+ (format t "~% [WARN] ~a: ~a~%" rel (i18n :defmacro))
89
123
  (incf *warnings*))))
90
- (format t "OK~%")))
124
+ (format t "~a~%" (i18n :ok))))
91
125
 
92
126
  ;; ── Main ──────────────────────────────────────────────────────────────
93
127
  (defun main ()
@@ -99,25 +133,26 @@
99
133
  '(".vscode" "test" "experiment" "tools" ".git")))
100
134
  (defmacro-allow (if (fourth args)
101
135
  (read-from-string (fourth args))
102
- '("compat-cl"))))
103
- ;; Load stub packages for CAD runtime symbols
136
+ '("compat-cl")))
137
+ (locale (fifth args)))
138
+ (when locale (setf *locale* locale))
104
139
  (load-stub-packages stub-file)
105
140
 
106
141
  (format t "~%==================================================~%")
107
- (format t " @lisp SBCL Lint~%")
108
- (format t " Source: ~a~%" (namestring (pathname src-dir)))
142
+ (format t "~a~%" (i18n :header))
143
+ (format t "~a: ~a~%" (i18n :source) (namestring (pathname src-dir)))
109
144
  (format t "==================================================~%~%")
110
145
  (setf *errors* 0 *warnings* 0 *checked* 0)
111
146
 
112
147
  (let ((files (walk-tree src-dir walk-exclude)))
113
- (format t " Found ~d .lsp files~%~%" (length files))
148
+ (format t "~a~%~%" (format nil (i18n :found) (length files)))
114
149
  (dolist (f files)
115
150
  (check-file f src-dir defmacro-allow)))
116
151
 
117
152
  (format t "~%==================================================~%")
118
- (format t " Scanned: ~d files~%" *checked*)
119
- (format t " Errors: ~d~%" *errors*)
120
- (format t " Warnings: ~d~%" *warnings*)
153
+ (format t "~a: ~d~%" (i18n :scanned) *checked*)
154
+ (format t "~a: ~d~%" (i18n :errors) *errors*)
155
+ (format t "~a: ~d~%" (i18n :warnings) *warnings*)
121
156
  (format t "==================================================~%~%")
122
157
  (if (> *errors* 0)
123
158
  (uiop:quit 1)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlisp/lint",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "AutoLISP static analysis tool — parens, security, conventions, SBCL syntax validation",
5
5
  "keywords": [
6
6
  "CAD",