@atlisp/lint 0.1.5 → 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.
Files changed (114) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +182 -58
  3. package/atlisp-lint.default.json +31 -1
  4. package/dist/atlisp-lint.default.json +90 -0
  5. package/dist/cache.d.ts +2 -2
  6. package/dist/cache.js +6 -6
  7. package/dist/checks/append-single.d.ts +3 -0
  8. package/dist/checks/append-single.js +17 -0
  9. package/dist/checks/arg-count.d.ts +3 -0
  10. package/dist/checks/arg-count.js +123 -0
  11. package/dist/checks/assoc-without-cdr.d.ts +5 -0
  12. package/dist/checks/assoc-without-cdr.js +32 -0
  13. package/dist/checks/comment-style.d.ts +3 -0
  14. package/dist/checks/comment-style.js +24 -0
  15. package/dist/checks/cond-duplicate.d.ts +5 -0
  16. package/dist/checks/cond-duplicate.js +52 -0
  17. package/dist/checks/cond-simplify.d.ts +3 -0
  18. package/dist/checks/cond-simplify.js +45 -0
  19. package/dist/checks/constant-condition.js +4 -4
  20. package/dist/checks/dangerous-calls.js +2 -2
  21. package/dist/checks/dangling-defun.d.ts +3 -0
  22. package/dist/checks/dangling-defun.js +10 -28
  23. package/dist/checks/double-not.js +1 -1
  24. package/dist/checks/duplicate-defun.d.ts +6 -0
  25. package/dist/checks/duplicate-defun.js +50 -0
  26. package/dist/checks/dynamic-doc.d.ts +3 -0
  27. package/dist/checks/dynamic-doc.js +21 -0
  28. package/dist/checks/empty-branch.js +1 -1
  29. package/dist/checks/empty-catch.d.ts +3 -0
  30. package/dist/checks/empty-catch.js +34 -0
  31. package/dist/checks/eq-usage.d.ts +3 -0
  32. package/dist/checks/eq-usage.js +25 -0
  33. package/dist/checks/error-handling.d.ts +3 -0
  34. package/dist/checks/error-handling.js +56 -0
  35. package/dist/checks/extra-parens.d.ts +3 -0
  36. package/dist/checks/extra-parens.js +45 -0
  37. package/dist/checks/function-complexity.js +1 -1
  38. package/dist/checks/function-order.d.ts +3 -0
  39. package/dist/checks/function-order.js +33 -0
  40. package/dist/checks/global-naming.d.ts +3 -0
  41. package/dist/checks/global-naming.js +62 -0
  42. package/dist/checks/identical-branches.d.ts +5 -0
  43. package/dist/checks/identical-branches.js +54 -0
  44. package/dist/checks/index.d.ts +3 -0
  45. package/dist/checks/index.js +117 -0
  46. package/dist/checks/lambda-syntax.d.ts +3 -0
  47. package/dist/checks/lambda-syntax.js +25 -0
  48. package/dist/checks/long-function-call.d.ts +3 -0
  49. package/dist/checks/long-function-call.js +54 -0
  50. package/dist/checks/loop-optimization.d.ts +3 -0
  51. package/dist/checks/loop-optimization.js +17 -0
  52. package/dist/checks/magic-number.d.ts +3 -0
  53. package/dist/checks/magic-number.js +21 -0
  54. package/dist/checks/misplaced-else.js +1 -1
  55. package/dist/checks/missing-export.js +2 -2
  56. package/dist/checks/mixed-indent.d.ts +3 -0
  57. package/dist/checks/mixed-indent.js +19 -0
  58. package/dist/checks/module-reg.js +1 -1
  59. package/dist/checks/multiple-setq.js +1 -1
  60. package/dist/checks/no-return.d.ts +3 -0
  61. package/dist/checks/no-return.js +51 -0
  62. package/dist/checks/nth-usage.d.ts +3 -0
  63. package/dist/checks/nth-usage.js +17 -0
  64. package/dist/checks/quote-style.d.ts +3 -0
  65. package/dist/checks/quote-style.js +25 -0
  66. package/dist/checks/quote-vs-function.js +1 -1
  67. package/dist/checks/recursive-call.js +1 -1
  68. package/dist/checks/redundant-if.d.ts +3 -0
  69. package/dist/checks/redundant-if.js +17 -0
  70. package/dist/checks/redundant-let.js +1 -1
  71. package/dist/checks/redundant-nil-else.js +1 -1
  72. package/dist/checks/redundant-progn.js +1 -1
  73. package/dist/checks/redundant-quotes.js +1 -1
  74. package/dist/checks/redundant-setq.js +1 -1
  75. package/dist/checks/self-compare.js +1 -1
  76. package/dist/checks/setq-multiple.d.ts +3 -0
  77. package/dist/checks/setq-multiple.js +17 -0
  78. package/dist/checks/setq-single-arg.d.ts +5 -0
  79. package/dist/checks/setq-single-arg.js +30 -0
  80. package/dist/checks/shadow-builtin.d.ts +3 -0
  81. package/dist/checks/shadow-builtin.js +77 -0
  82. package/dist/checks/single-arg-and-or.js +1 -1
  83. package/dist/checks/strcat-usage.d.ts +3 -0
  84. package/dist/checks/strcat-usage.js +25 -0
  85. package/dist/checks/type-check.d.ts +3 -0
  86. package/dist/checks/type-check.js +26 -0
  87. package/dist/checks/unused-let.js +1 -1
  88. package/dist/checks/unused-package-dep.js +3 -3
  89. package/dist/checks/variable-shadow.js +1 -1
  90. package/dist/checks/while-constant.d.ts +5 -0
  91. package/dist/checks/while-constant.js +40 -0
  92. package/dist/config.d.ts +1 -0
  93. package/dist/config.js +70 -2
  94. package/dist/disable.js +1 -1
  95. package/dist/formatters.d.ts +1 -0
  96. package/dist/formatters.js +18 -2
  97. package/dist/index.js +53 -13
  98. package/dist/lib/lint-sbcl.lisp +161 -0
  99. package/dist/locale.js +24 -0
  100. package/dist/presets.d.ts +4 -0
  101. package/dist/presets.js +158 -0
  102. package/dist/project.js +37 -6
  103. package/dist/rules.d.ts +9 -0
  104. package/dist/rules.js +238 -0
  105. package/dist/runner.d.ts +2 -0
  106. package/dist/runner.js +198 -11
  107. package/dist/sbcl.js +1 -1
  108. package/dist/stub-packages.json +41 -0
  109. package/dist/types.d.ts +6 -0
  110. package/dist/validate.d.ts +8 -0
  111. package/dist/validate.js +125 -0
  112. package/dist/watch.d.ts +9 -0
  113. package/dist/watch.js +113 -0
  114. package/package.json +1 -1
@@ -0,0 +1,125 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateConfig = validateConfig;
4
+ const VALID_RULES = [
5
+ 'append_single',
6
+ 'arg_count',
7
+ 'assoc_without_cdr',
8
+ 'bare_function_names',
9
+ 'cl_syntax',
10
+ 'command_shell',
11
+ 'comment_style',
12
+ 'commented_code',
13
+ 'cond_simplify',
14
+ 'cond_duplicate',
15
+ 'constant_condition',
16
+ 'dangling_defun',
17
+ 'double_not',
18
+ 'duplicate_defun',
19
+ 'dynamic_doc',
20
+ 'empty_branch',
21
+ 'empty_catch',
22
+ 'empty_comment',
23
+ 'encoding',
24
+ 'eq_usage',
25
+ 'error_handling',
26
+ 'extra_parens',
27
+ 'function_complexity',
28
+ 'function_order',
29
+ 'global_naming',
30
+ 'identical_branches',
31
+ 'lambda_syntax',
32
+ 'line_length',
33
+ 'long_function_call',
34
+ 'loop_optimization',
35
+ 'magic_number',
36
+ 'misplaced_else',
37
+ 'missing_doc',
38
+ 'missing_export',
39
+ 'mixed_indent',
40
+ 'module_registration',
41
+ 'multiple_setq',
42
+ 'namespace_header',
43
+ 'no_return',
44
+ 'nth_usage',
45
+ 'open_without_close',
46
+ 'parameter_naming',
47
+ 'parens',
48
+ 'quit_exit',
49
+ 'quote_style',
50
+ 'quote_vs_function',
51
+ 'recursive_call',
52
+ 'redundant_cond',
53
+ 'redundant_if',
54
+ 'redundant_let',
55
+ 'redundant_nil_else',
56
+ 'redundant_progn',
57
+ 'redundant_quotes',
58
+ 'redundant_setq',
59
+ 'self_compare',
60
+ 'setq_multiple',
61
+ 'setq_single_arg',
62
+ 'shadow_builtin',
63
+ 'single_arg_and_or',
64
+ 'startapp',
65
+ 'strcat_usage',
66
+ 'token_in_url',
67
+ 'trailing_paren',
68
+ 'trailing_whitespace',
69
+ 'type_check',
70
+ 'unused_let_binding',
71
+ 'unused_local_fun',
72
+ 'unused_package_dep',
73
+ 'unused_parameter',
74
+ 'unused_variable',
75
+ 'variable_shadow',
76
+ 'while_constant',
77
+ 'vl_registry_write',
78
+ 'vlax_without_loading',
79
+ ];
80
+ const VALID_SEVERITIES = ['off', 'warn', 'error'];
81
+ function validateConfig(config) {
82
+ const errors = [];
83
+ if (config.locale && config.locale !== 'zh' && config.locale !== 'en') {
84
+ errors.push({ path: 'locale', message: `Invalid locale '${config.locale}', expected 'zh' or 'en'` });
85
+ }
86
+ if (config.checks) {
87
+ for (const [rule, sev] of Object.entries(config.checks)) {
88
+ if (!VALID_RULES.includes(rule)) {
89
+ errors.push({ path: `checks.${rule}`, message: `Unknown rule '${rule}'` });
90
+ }
91
+ if (!VALID_SEVERITIES.includes(sev)) {
92
+ errors.push({
93
+ path: `checks.${rule}`,
94
+ message: `Invalid severity '${sev}', expected 'off', 'warn', or 'error'`,
95
+ });
96
+ }
97
+ }
98
+ }
99
+ if (config.source) {
100
+ if (!Array.isArray(config.source.globs)) {
101
+ errors.push({ path: 'source.globs', message: 'Must be an array of glob patterns' });
102
+ }
103
+ if (!Array.isArray(config.source.exclude)) {
104
+ errors.push({ path: 'source.exclude', message: 'Must be an array of glob patterns' });
105
+ }
106
+ }
107
+ if (config.line_length) {
108
+ if (typeof config.line_length.max !== 'number' || config.line_length.max < 1) {
109
+ errors.push({ path: 'line_length.max', message: 'Must be a positive number' });
110
+ }
111
+ if (typeof config.line_length.tab_width !== 'number' || config.line_length.tab_width < 1) {
112
+ errors.push({ path: 'line_length.tab_width', message: 'Must be a positive number' });
113
+ }
114
+ }
115
+ if (config.function_complexity) {
116
+ if (typeof config.function_complexity.max_lines !== 'number' || config.function_complexity.max_lines < 1) {
117
+ errors.push({ path: 'function_complexity.max_lines', message: 'Must be a positive number' });
118
+ }
119
+ if (typeof config.function_complexity.max_nesting !== 'number' || config.function_complexity.max_nesting < 1) {
120
+ errors.push({ path: 'function_complexity.max_nesting', message: 'Must be a positive number' });
121
+ }
122
+ }
123
+ return errors;
124
+ }
125
+ //# sourceMappingURL=validate.js.map
@@ -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
package/dist/watch.js ADDED
@@ -0,0 +1,113 @@
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 {
69
+ /* ignore */
70
+ }
71
+ }
72
+ }
73
+ console.log(`\n${(0, locale_1.t)('index.watching')} (${files.length} files)`);
74
+ console.log((0, locale_1.t)('index.watch_hint'));
75
+ // Cleanup on exit
76
+ process.on('SIGINT', () => {
77
+ for (const w of watchers)
78
+ w.close();
79
+ process.exit(0);
80
+ });
81
+ process.on('SIGTERM', () => {
82
+ for (const w of watchers)
83
+ w.close();
84
+ process.exit(0);
85
+ });
86
+ }
87
+ function runLint(files, rootDir, format, config) {
88
+ // Clear console
89
+ process.stdout.write('\x1Bc');
90
+ const issues = (0, runner_1.lintFiles)(files, config, rootDir);
91
+ const fileContents = new Map();
92
+ for (const iss of issues) {
93
+ if (!fileContents.has(iss.file)) {
94
+ const fp = path.resolve(rootDir, iss.file);
95
+ try {
96
+ fileContents.set(iss.file, fs.readFileSync(fp, 'utf-8'));
97
+ }
98
+ catch {
99
+ /* ignore */
100
+ }
101
+ }
102
+ }
103
+ if (format === 'json') {
104
+ console.log((0, formatters_1.formatJson)(issues));
105
+ }
106
+ else {
107
+ console.log((0, formatters_1.formatDefault)(issues, fileContents));
108
+ }
109
+ const errorCount = issues.filter(i => i.severity === 'error').length;
110
+ const warningCount = issues.filter(i => i.severity === 'warn').length;
111
+ console.log(`\n[${new Date().toLocaleTimeString()}] ${(0, locale_1.t)('index.watch_status', files.length, errorCount, warningCount)}`);
112
+ }
113
+ //# sourceMappingURL=watch.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlisp/lint",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "AutoLISP static analysis tool — parens, security, conventions, SBCL syntax validation",
5
5
  "keywords": [
6
6
  "CAD",