@atlisp/lint 0.2.11 → 0.2.13

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 (48) hide show
  1. package/atlisp-lint.schema.json +32 -2
  2. package/dist/cache.js +19 -9
  3. package/dist/checks/builtin-arg-count.d.ts +1 -0
  4. package/dist/checks/builtin-arg-count.js +5 -0
  5. package/dist/checks/dangerous-calls.js +1 -0
  6. package/dist/checks/dangling-defun.d.ts +7 -0
  7. package/dist/checks/dangling-defun.js +19 -0
  8. package/dist/checks/global-function-naming.js +159 -35
  9. package/dist/checks/missing-princ.js +2 -2
  10. package/dist/checks/nth-usage.d.ts +1 -0
  11. package/dist/checks/nth-usage.js +16 -1
  12. package/dist/checks/unused-package-dep.d.ts +1 -0
  13. package/dist/checks/unused-package-dep.js +53 -0
  14. package/dist/cli/collector.d.ts +7 -0
  15. package/dist/cli/collector.js +154 -0
  16. package/dist/cli/parser.d.ts +30 -0
  17. package/dist/cli/parser.js +119 -0
  18. package/dist/config.js +32 -6
  19. package/dist/disable.js +12 -0
  20. package/dist/fixes/index.d.ts +8 -0
  21. package/dist/fixes/index.js +200 -0
  22. package/dist/index.js +56 -236
  23. package/dist/locale.js +30 -2
  24. package/dist/presets.js +24 -0
  25. package/dist/project.js +182 -134
  26. package/dist/rules.d.ts +1 -0
  27. package/dist/rules.js +85 -0
  28. package/dist/runner.d.ts +2 -3
  29. package/dist/runner.js +46 -371
  30. package/dist/types.d.ts +6 -0
  31. package/dist/utils.d.ts +4 -0
  32. package/dist/utils.js +43 -0
  33. package/dist/validate.js +12 -0
  34. package/dist/visitor-runner.d.ts +28 -0
  35. package/dist/visitor-runner.js +115 -1
  36. package/dist/visitors/equal-nil.d.ts +8 -0
  37. package/dist/visitors/equal-nil.js +26 -0
  38. package/dist/visitors/index.d.ts +5 -0
  39. package/dist/visitors/index.js +14 -0
  40. package/dist/visitors/progn-in-cond.d.ts +8 -0
  41. package/dist/visitors/progn-in-cond.js +33 -0
  42. package/dist/visitors/redundant-and-or.d.ts +8 -0
  43. package/dist/visitors/redundant-and-or.js +27 -0
  44. package/dist/visitors/redundant-car-cdr.d.ts +8 -0
  45. package/dist/visitors/redundant-car-cdr.js +35 -0
  46. package/dist/visitors/types.d.ts +13 -0
  47. package/dist/visitors/types.js +72 -0
  48. package/package.json +1 -1
package/dist/runner.js CHANGED
@@ -33,11 +33,10 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.FIXABLE_RULES = void 0;
36
+ exports.FIXABLE_RULES = exports.applyFixes = void 0;
37
37
  exports.runChecks = runChecks;
38
38
  exports.lintFiles = lintFiles;
39
39
  exports.lintFilesParallel = lintFilesParallel;
40
- exports.applyFixes = applyFixes;
41
40
  exports.parseIgnoreFile = parseIgnoreFile;
42
41
  exports.fixFile = fixFile;
43
42
  const fs = __importStar(require("fs"));
@@ -110,8 +109,8 @@ function runChecks(content, file, config) {
110
109
  }
111
110
  }
112
111
  }
113
- catch {
114
- // Check failed, continue with remaining checks
112
+ catch (e) {
113
+ console.warn(`[lint] check "${rule}" failed for ${file}: ${e instanceof Error ? e.message : String(e)}`);
115
114
  }
116
115
  }
117
116
  function addIssues(ruleIssues) {
@@ -198,6 +197,17 @@ function runChecks(content, file, config) {
198
197
  'identical_branches',
199
198
  'while_constant',
200
199
  'cond_duplicate',
200
+ 'command_s',
201
+ 'zerop_usage',
202
+ 'progn_in_body',
203
+ 'if_progn_both',
204
+ 'redundant_cond',
205
+ 'selection_set_leak',
206
+ 'empty_branch_cond',
207
+ 'progn_in_cond',
208
+ 'redundant_car_cdr',
209
+ 'equal_nil',
210
+ 'redundant_and_or',
201
211
  ]);
202
212
  const needsAst = Array.from(astRules).some(r => checks[r] !== 'off');
203
213
  if (needsAst) {
@@ -206,35 +216,49 @@ function runChecks(content, file, config) {
206
216
  const visitorIssues = (0, visitor_runner_1.runChecksWithVisitor)(ast, file, config, disableMap);
207
217
  addIssues(visitorIssues);
208
218
  }
209
- catch {
210
- // AST-based checks are skipped, text-based checks above still report issues
219
+ catch (e) {
220
+ console.warn(`[lint] AST parse/visitor failed for ${file}: ${e instanceof Error ? e.message : String(e)}`);
211
221
  }
212
222
  }
213
223
  return issues;
214
224
  }
215
- function lintFiles(files, config, rootDir) {
225
+ function lintFiles(files, config, rootDir, contentCache) {
216
226
  (0, locale_1.setLocale)(config.locale || 'zh');
217
227
  const allIssues = [];
218
- for (const filepath of files) {
228
+ const total = files.length;
229
+ const showProgress = process.stderr.isTTY && total > 5;
230
+ for (let fi = 0; fi < total; fi++) {
231
+ const filepath = files[fi];
219
232
  const relPath = path.relative(rootDir, filepath);
233
+ if (showProgress) {
234
+ process.stderr.write(`\r[${fi + 1}/${total}] ${relPath} `);
235
+ }
220
236
  let content;
221
- try {
222
- content = fs.readFileSync(filepath, 'utf-8');
237
+ if (contentCache && contentCache.has(filepath)) {
238
+ content = contentCache.get(filepath);
223
239
  }
224
- catch {
225
- allIssues.push({
226
- file: relPath,
227
- line: 1,
228
- severity: 'error',
229
- rule: 'read',
230
- message: (0, locale_1.t)('runner.read_error'),
231
- });
232
- continue;
240
+ else {
241
+ try {
242
+ content = fs.readFileSync(filepath, 'utf-8');
243
+ }
244
+ catch {
245
+ allIssues.push({
246
+ file: relPath,
247
+ line: 1,
248
+ severity: 'error',
249
+ rule: 'read',
250
+ message: (0, locale_1.t)('runner.read_error'),
251
+ });
252
+ continue;
253
+ }
233
254
  }
234
255
  const override = (0, config_1.findOverrides)(filepath);
235
256
  const effectiveConfig = override ? (0, config_1.mergeOverrides)(config, override) : config;
236
257
  allIssues.push(...runChecks(content, relPath, effectiveConfig));
237
258
  }
259
+ if (showProgress) {
260
+ process.stderr.write('\r' + ' '.repeat(60) + '\r');
261
+ }
238
262
  return allIssues;
239
263
  }
240
264
  function lintFilesParallel(files, config, rootDir) {
@@ -302,358 +326,9 @@ function lintFilesParallel(files, config, rootDir) {
302
326
  resolve([]);
303
327
  });
304
328
  }
305
- function findMatchingParen(s, start) {
306
- if (s[start] !== '(')
307
- return start;
308
- let depth = 0;
309
- for (let i = start; i < s.length; i++) {
310
- if (s[i] === '"') {
311
- i++;
312
- while (i < s.length && s[i] !== '"') {
313
- if (s[i] === '\\')
314
- i++;
315
- i++;
316
- }
317
- continue;
318
- }
319
- if (s[i] === '(')
320
- depth++;
321
- else if (s[i] === ')') {
322
- depth--;
323
- if (depth === 0)
324
- return i;
325
- }
326
- }
327
- return s.length - 1;
328
- }
329
- function extractForm(s, start) {
330
- let i = start;
331
- while (i < s.length && s[i] === ' ')
332
- i++;
333
- if (i >= s.length)
334
- return ['', i];
335
- if (s[i] !== '(') {
336
- const m = s.slice(i).match(/^\S+/);
337
- if (m)
338
- return [m[0], i + m[0].length];
339
- return ['', i];
340
- }
341
- const end = findMatchingParen(s, i);
342
- return [s.slice(i, end + 1), end + 1];
343
- }
344
- // ===== FIX APPLICATION =====
345
- exports.FIXABLE_RULES = new Set([
346
- 'redundant_quotes',
347
- 'double_not',
348
- 'redundant_nil_else',
349
- 'single_arg_and_or',
350
- 'redundant_setq',
351
- 'redundant_progn',
352
- 'redundant_let',
353
- 'quote_style',
354
- 'redundant_if',
355
- 'misplaced_else',
356
- 'setq_multiple',
357
- 'append_single',
358
- 'nth_usage',
359
- 'setq_single_arg',
360
- 'extra_parens',
361
- 'empty_branch',
362
- 'comment_style',
363
- 'eq_usage',
364
- 'cond_simplify',
365
- 'self_compare',
366
- 'while_constant',
367
- 'redundant_list',
368
- ]);
369
- function applyFixes(issues, content, filepath) {
370
- const lines = content.split('\n');
371
- const fixedLines = new Set();
372
- const fixesByRule = new Map();
373
- for (const iss of issues) {
374
- if (iss.file !== filepath)
375
- continue;
376
- const set = fixesByRule.get(iss.rule) || new Set();
377
- set.add(iss.line);
378
- fixesByRule.set(iss.rule, set);
379
- }
380
- const fixableRules = exports.FIXABLE_RULES;
381
- for (const [rule, lineSet] of fixesByRule) {
382
- if (!fixableRules.has(rule))
383
- continue;
384
- const sortedLines = Array.from(lineSet).sort((a, b) => b - a);
385
- for (const line of sortedLines) {
386
- const idx = line - 1;
387
- if (idx < 0 || idx >= lines.length)
388
- continue;
389
- const lineContent = lines[idx];
390
- switch (rule) {
391
- case 'redundant_quotes': {
392
- const fixed = lineContent.replace(/''(\S)/g, "'$1");
393
- if (fixed !== lineContent) {
394
- lines[idx] = fixed;
395
- fixedLines.add(idx);
396
- }
397
- break;
398
- }
399
- case 'double_not': {
400
- const fixed = lineContent.replace(/\(not\s+\(not\s+/g, '(not ');
401
- if (fixed !== lineContent) {
402
- lines[idx] = fixed;
403
- fixedLines.add(idx);
404
- }
405
- break;
406
- }
407
- case 'redundant_nil_else': {
408
- const fixed = lineContent.replace(/\s+nil\s*\)$/, ')');
409
- if (fixed !== lineContent) {
410
- lines[idx] = fixed;
411
- fixedLines.add(idx);
412
- }
413
- break;
414
- }
415
- case 'single_arg_and_or': {
416
- const m = lineContent.match(/\((and|or)\s+([^)\s]+)\s*\)/);
417
- if (m) {
418
- lines[idx] = m[2];
419
- fixedLines.add(idx);
420
- }
421
- break;
422
- }
423
- case 'redundant_progn': {
424
- const proIdx = lineContent.indexOf('(progn ');
425
- if (proIdx !== -1) {
426
- const beforePro = lineContent.slice(0, proIdx);
427
- const close = findMatchingParen(lineContent, proIdx);
428
- if (close > proIdx) {
429
- const inner = lineContent.slice(proIdx + 7, close);
430
- const rest = lineContent.slice(close + 1);
431
- const fixed = beforePro + inner + rest;
432
- if (fixed !== lineContent) {
433
- lines[idx] = fixed;
434
- fixedLines.add(idx);
435
- }
436
- }
437
- }
438
- break;
439
- }
440
- case 'redundant_let': {
441
- const fixed = lineContent.replace(/\(let\s+\(\)\s*/, '(progn ');
442
- if (fixed !== lineContent) {
443
- lines[idx] = fixed;
444
- fixedLines.add(idx);
445
- }
446
- break;
447
- }
448
- case 'quote_style': {
449
- const qIdx = lineContent.indexOf('(quote ');
450
- if (qIdx !== -1) {
451
- const beforeQ = lineContent.slice(0, qIdx);
452
- const close = findMatchingParen(lineContent, qIdx);
453
- if (close > qIdx) {
454
- const quoted = lineContent.slice(qIdx + 7, close);
455
- const rest = lineContent.slice(close + 1);
456
- const fixed = beforeQ + "'" + quoted + rest;
457
- if (fixed !== lineContent) {
458
- lines[idx] = fixed;
459
- fixedLines.add(idx);
460
- }
461
- }
462
- }
463
- break;
464
- }
465
- case 'redundant_if': {
466
- const pIdx = lineContent.indexOf('(progn ');
467
- if (pIdx !== -1) {
468
- const beforeP = lineContent.slice(0, pIdx);
469
- const close = findMatchingParen(lineContent, pIdx);
470
- if (close > pIdx) {
471
- const inner = lineContent.slice(pIdx + 7, close);
472
- const rest = lineContent.slice(close + 1);
473
- const fixed = beforeP + inner + rest;
474
- if (fixed !== lineContent) {
475
- lines[idx] = fixed;
476
- fixedLines.add(idx);
477
- }
478
- }
479
- }
480
- break;
481
- }
482
- case 'misplaced_else': {
483
- const ifStart = lineContent.indexOf('(if (not ');
484
- if (ifStart !== -1) {
485
- const notIdx = lineContent.indexOf('(not ', ifStart);
486
- if (notIdx === -1)
487
- break;
488
- const notClose = findMatchingParen(lineContent, notIdx);
489
- if (notClose <= notIdx)
490
- break;
491
- const ifClose = findMatchingParen(lineContent, ifStart);
492
- if (ifClose <= ifStart)
493
- break;
494
- const indent = lineContent.slice(0, ifStart);
495
- const condVar = lineContent.slice(notIdx + 5, notClose);
496
- const branchContent = lineContent.slice(notClose + 1, ifClose).trim();
497
- const [thenForm, thenEnd] = extractForm(branchContent, 0);
498
- const elseForm = branchContent.slice(thenEnd).trim();
499
- if (thenForm && elseForm) {
500
- const rest = lineContent.slice(ifClose + 1);
501
- const fixed = indent + '(if ' + condVar + ' ' + elseForm + ' ' + thenForm + ')' + rest;
502
- if (fixed !== lineContent) {
503
- lines[idx] = fixed;
504
- fixedLines.add(idx);
505
- }
506
- }
507
- }
508
- break;
509
- }
510
- case 'redundant_setq': {
511
- const trimmed = lines[idx].trim();
512
- if (/^\(setq\s+(\S+)\s+\1\s*\)$/.test(trimmed)) {
513
- lines.splice(idx, 1);
514
- }
515
- break;
516
- }
517
- case 'setq_multiple': {
518
- const fixed = lineContent.replace(/\)\(setq\s+/g, ' ');
519
- if (fixed !== lineContent) {
520
- const merged = lineContent.replace(/^\(\s*setq\s+/, '(setq ');
521
- if (merged.includes('setq') && !merged.match(/\)\(/)) {
522
- lines[idx] = merged;
523
- fixedLines.add(idx);
524
- }
525
- else {
526
- const simplified = lineContent.replace(/\)\(setq\s+/g, '\n');
527
- if (simplified !== lineContent) {
528
- lines[idx] = simplified;
529
- fixedLines.add(idx);
530
- }
531
- }
532
- }
533
- break;
534
- }
535
- case 'append_single': {
536
- const aIdx = lineContent.indexOf('(append ');
537
- if (aIdx !== -1) {
538
- const close = findMatchingParen(lineContent, aIdx);
539
- if (close > aIdx) {
540
- const inner = lineContent.slice(aIdx + 8, close);
541
- const listMatch = inner.match(/^\(list\s+(.*)\)\s*$/);
542
- if (listMatch) {
543
- const fixed = lineContent.slice(0, aIdx) + '(cons ' + listMatch[1] + ')' + lineContent.slice(close + 1);
544
- if (fixed !== lineContent) {
545
- lines[idx] = fixed;
546
- fixedLines.add(idx);
547
- }
548
- }
549
- }
550
- }
551
- break;
552
- }
553
- case 'nth_usage': {
554
- const fixed = lineContent.replace(/\(nth\s+0\s+/g, '(car ');
555
- if (fixed !== lineContent) {
556
- lines[idx] = fixed;
557
- fixedLines.add(idx);
558
- }
559
- break;
560
- }
561
- case 'setq_single_arg': {
562
- if (/^\s*\(setq\s+\S+\s*\)\s*$/.test(lines[idx])) {
563
- lines.splice(idx, 1);
564
- }
565
- break;
566
- }
567
- case 'extra_parens': {
568
- const fixed = lineContent.replace(/\){2,}/g, ')');
569
- if (fixed !== lineContent) {
570
- lines[idx] = fixed;
571
- fixedLines.add(idx);
572
- }
573
- break;
574
- }
575
- case 'empty_branch': {
576
- const fixed = lineContent.replace(/\(if\s+\S+\s*\)/g, m => m.slice(0, -1) + ' nil)');
577
- if (fixed !== lineContent) {
578
- lines[idx] = fixed;
579
- fixedLines.add(idx);
580
- }
581
- break;
582
- }
583
- case 'comment_style': {
584
- const fixed = lineContent.replace(/^(\s*;)([^ ;|].*)$/gm, '$1 $2');
585
- if (fixed !== lineContent) {
586
- lines[idx] = fixed;
587
- fixedLines.add(idx);
588
- }
589
- break;
590
- }
591
- case 'eq_usage': {
592
- const fixed = lineContent.replace(/\(eq\s+(\S+)\s+(\d+)\s*\)/g, '(= $1 $2)');
593
- if (fixed !== lineContent) {
594
- lines[idx] = fixed;
595
- fixedLines.add(idx);
596
- }
597
- break;
598
- }
599
- case 'cond_simplify': {
600
- const condIdx = lineContent.indexOf('(cond ');
601
- if (condIdx !== -1) {
602
- const condEnd = findMatchingParen(lineContent, condIdx);
603
- if (condEnd > condIdx) {
604
- const inner = lineContent.slice(condIdx + 6, condEnd).trim();
605
- const branchOpen = inner.indexOf('(');
606
- if (branchOpen !== -1) {
607
- const branchEnd = findMatchingParen(inner, branchOpen);
608
- if (branchEnd > branchOpen) {
609
- const indent = lineContent.slice(0, condIdx);
610
- const branchContent = inner.slice(branchOpen + 1, branchEnd).trim();
611
- const space = branchContent.search(/\s+/);
612
- if (space !== -1) {
613
- const testExpr = branchContent.slice(0, space);
614
- const bodyExpr = branchContent.slice(space).trim();
615
- const rest = lineContent.slice(condEnd + 1);
616
- const fixed = indent + '(if ' + testExpr + ' ' + bodyExpr + ')' + rest;
617
- if (fixed !== lineContent) {
618
- lines[idx] = fixed;
619
- fixedLines.add(idx);
620
- }
621
- }
622
- }
623
- }
624
- }
625
- }
626
- break;
627
- }
628
- case 'self_compare': {
629
- const fixed = lineContent.replace(/\((?:[=/<>]+|eq|equal)\s+(\S+)\s+\1\s*\)/g, 'T');
630
- if (fixed !== lineContent) {
631
- lines[idx] = fixed;
632
- fixedLines.add(idx);
633
- }
634
- break;
635
- }
636
- case 'while_constant': {
637
- const trimmed = lines[idx].trim();
638
- const nilMatch = trimmed.match(/^\(\s*while\s+nil\s+(.*)\)\s*$/);
639
- if (nilMatch) {
640
- lines[idx] = lines[idx].replace(trimmed, 'nil');
641
- }
642
- break;
643
- }
644
- case 'redundant_list': {
645
- const fixed = lineContent.replace(/\(\s*list\s*\)/g, 'nil');
646
- if (fixed !== lineContent) {
647
- lines[idx] = fixed;
648
- fixedLines.add(idx);
649
- }
650
- break;
651
- }
652
- }
653
- }
654
- }
655
- return lines.join('\n');
656
- }
329
+ var index_1 = require("./fixes/index");
330
+ Object.defineProperty(exports, "applyFixes", { enumerable: true, get: function () { return index_1.applyFixesFromProviders; } });
331
+ Object.defineProperty(exports, "FIXABLE_RULES", { enumerable: true, get: function () { return index_1.FIXABLE_RULES; } });
657
332
  function parseIgnoreFile(rootDir) {
658
333
  const ignoreFile = path.join(rootDir, '.atlisp-lint-ignore');
659
334
  if (!fs.existsSync(ignoreFile))
package/dist/types.d.ts CHANGED
@@ -24,6 +24,7 @@ export interface DangerousCallsConfig {
24
24
  command_shell: Severity;
25
25
  startapp: Severity;
26
26
  vl_registry_write: Severity;
27
+ eval: Severity;
27
28
  }
28
29
  export interface ModuleRegistrationConfig extends CheckConfig {
29
30
  patterns: string[];
@@ -42,6 +43,10 @@ export interface SbclConfig {
42
43
  walk_exclude: string[];
43
44
  defmacro_allow_files: string[];
44
45
  }
46
+ export interface ProjectAnalysisConfig {
47
+ maxFiles: number;
48
+ batchSize: number;
49
+ }
45
50
  export interface SourceConfig {
46
51
  globs: string[];
47
52
  exclude: string[];
@@ -66,6 +71,7 @@ export interface LintConfig {
66
71
  namespace_header: NamespaceHeaderConfig;
67
72
  bare_function_names: BareFunctionNamesConfig;
68
73
  sbcl: SbclConfig;
74
+ project_analysis: ProjectAnalysisConfig;
69
75
  preset?: string;
70
76
  }
71
77
  export interface FormattedResult {
package/dist/utils.d.ts CHANGED
@@ -7,6 +7,10 @@ export declare function codeLines(content: string): Generator<{
7
7
  text: string;
8
8
  stripped: string;
9
9
  }>;
10
+ /** Find matching closing paren (string/comment aware) */
11
+ export declare function findMatchingParen(s: string, start: number): number;
12
+ /** Extract the next s-expression form starting at position */
13
+ export declare function extractForm(s: string, start: number): [string, number];
10
14
  /** Extract string literals from a line */
11
15
  export declare function extractStrings(line: string): string[];
12
16
  //# sourceMappingURL=utils.d.ts.map
package/dist/utils.js CHANGED
@@ -3,6 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.stripLine = stripLine;
4
4
  exports.stripLineRaw = stripLineRaw;
5
5
  exports.codeLines = codeLines;
6
+ exports.findMatchingParen = findMatchingParen;
7
+ exports.extractForm = extractForm;
6
8
  exports.extractStrings = extractStrings;
7
9
  /** Strip string contents and comments from a line of AutoLISP code */
8
10
  function stripLine(line) {
@@ -67,6 +69,47 @@ function* codeLines(content) {
67
69
  };
68
70
  }
69
71
  }
72
+ /** Find matching closing paren (string/comment aware) */
73
+ function findMatchingParen(s, start) {
74
+ if (s[start] !== '(')
75
+ return start;
76
+ let depth = 0;
77
+ for (let i = start; i < s.length; i++) {
78
+ if (s[i] === '"') {
79
+ i++;
80
+ while (i < s.length && s[i] !== '"') {
81
+ if (s[i] === '\\')
82
+ i++;
83
+ i++;
84
+ }
85
+ continue;
86
+ }
87
+ if (s[i] === '(')
88
+ depth++;
89
+ else if (s[i] === ')') {
90
+ depth--;
91
+ if (depth === 0)
92
+ return i;
93
+ }
94
+ }
95
+ return s.length - 1;
96
+ }
97
+ /** Extract the next s-expression form starting at position */
98
+ function extractForm(s, start) {
99
+ let i = start;
100
+ while (i < s.length && s[i] === ' ')
101
+ i++;
102
+ if (i >= s.length)
103
+ return ['', i];
104
+ if (s[i] !== '(') {
105
+ const m = s.slice(i).match(/^\S+/);
106
+ if (m)
107
+ return [m[0], i + m[0].length];
108
+ return ['', i];
109
+ }
110
+ const end = findMatchingParen(s, i);
111
+ return [s.slice(i, end + 1), end + 1];
112
+ }
70
113
  /** Extract string literals from a line */
71
114
  function extractStrings(line) {
72
115
  const strings = [];
package/dist/validate.js CHANGED
@@ -89,6 +89,18 @@ const VALID_RULES = [
89
89
  'redundant_entmake',
90
90
  'missing_princ',
91
91
  'global_function_naming',
92
+ 'command_s',
93
+ 'zerop_usage',
94
+ 'progn_in_body',
95
+ 'if_progn_both',
96
+ 'redundant_cond',
97
+ 'selection_set_leak',
98
+ 'empty_branch_cond',
99
+ 'function_reference',
100
+ 'progn_in_cond',
101
+ 'redundant_car_cdr',
102
+ 'equal_nil',
103
+ 'redundant_and_or',
92
104
  ];
93
105
  const VALID_SEVERITIES = ['off', 'info', 'warn', 'error'];
94
106
  function validateConfig(config) {
@@ -1,4 +1,32 @@
1
1
  import { Issue, LintConfig } from './types';
2
2
  import { AstNode } from '@atlisp/parser';
3
+ export interface CollectState {
4
+ openCount: number;
5
+ closeCount: number;
6
+ setqDefs: Map<string, {
7
+ line: number;
8
+ file: string;
9
+ }>;
10
+ symbolRefs: Map<string, number>;
11
+ condKeys: Map<number, Set<string>>;
12
+ defunScopes: Array<{
13
+ name: string;
14
+ params: string[];
15
+ body: AstNode[];
16
+ line: number;
17
+ file: string;
18
+ }>;
19
+ letScopes: Array<{
20
+ bindings: string[];
21
+ body: AstNode[];
22
+ line: number;
23
+ }>;
24
+ dangerousCalls: Array<{
25
+ name: string;
26
+ node: AstNode;
27
+ }>;
28
+ ssgetCount: number;
29
+ sssetCount: number;
30
+ }
3
31
  export declare function runChecksWithVisitor(ast: AstNode, file: string, config: LintConfig, disableMap: Map<string, Set<number>>): Issue[];
4
32
  //# sourceMappingURL=visitor-runner.d.ts.map