@atlisp/lint 0.1.23 → 0.1.25

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 (50) hide show
  1. package/atlisp-lint.default.json +2 -1
  2. package/dist/atlisp-lint.default.json +90 -0
  3. package/dist/checks/arg-count.js +1 -1
  4. package/dist/checks/assoc-without-cdr.js +1 -1
  5. package/dist/checks/builtin-arg-count.d.ts +3 -0
  6. package/dist/checks/builtin-arg-count.js +282 -0
  7. package/dist/checks/cond-duplicate.js +1 -1
  8. package/dist/checks/constant-condition.js +3 -3
  9. package/dist/checks/dangerous-calls.js +1 -1
  10. package/dist/checks/dangling-defun.js +1 -1
  11. package/dist/checks/double-not.js +1 -1
  12. package/dist/checks/empty-branch.js +1 -1
  13. package/dist/checks/empty-catch.js +1 -1
  14. package/dist/checks/function-complexity.js +1 -1
  15. package/dist/checks/global-naming.js +1 -1
  16. package/dist/checks/identical-branches.js +1 -1
  17. package/dist/checks/misplaced-else.js +1 -1
  18. package/dist/checks/multiple-setq.js +1 -1
  19. package/dist/checks/no-return.js +1 -1
  20. package/dist/checks/open-close.js +1 -1
  21. package/dist/checks/parameter-naming.js +1 -1
  22. package/dist/checks/quote-vs-function.js +1 -1
  23. package/dist/checks/recursive-call.js +1 -1
  24. package/dist/checks/redundant-let.js +1 -1
  25. package/dist/checks/redundant-nil-else.js +1 -1
  26. package/dist/checks/redundant-progn.js +1 -1
  27. package/dist/checks/redundant-quotes.js +1 -1
  28. package/dist/checks/redundant-setq.js +1 -1
  29. package/dist/checks/self-compare.js +1 -1
  30. package/dist/checks/setq-single-arg.js +1 -1
  31. package/dist/checks/single-arg-and-or.js +1 -1
  32. package/dist/checks/undeclared-setq.js +1 -1
  33. package/dist/checks/unused-catch-result.js +1 -1
  34. package/dist/checks/unused-let.js +1 -1
  35. package/dist/checks/unused-local-fun.js +1 -1
  36. package/dist/checks/unused-package-dep.js +1 -1
  37. package/dist/checks/unused-param.js +1 -1
  38. package/dist/checks/unused-variable.js +1 -1
  39. package/dist/checks/variable-shadow.js +1 -1
  40. package/dist/checks/while-constant.js +1 -1
  41. package/dist/formatters.d.ts +0 -1
  42. package/dist/formatters.js +0 -16
  43. package/dist/lib/lint-sbcl.lisp +161 -0
  44. package/dist/locale.js +2 -0
  45. package/dist/project.js +5 -5
  46. package/dist/rules.js +2 -1
  47. package/dist/runner.d.ts +0 -1
  48. package/dist/runner.js +150 -100
  49. package/dist/stub-packages.json +41 -0
  50. package/package.json +2 -2
package/dist/runner.js CHANGED
@@ -35,7 +35,6 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.FIXABLE_RULES = void 0;
37
37
  exports.runChecks = runChecks;
38
- exports.runChecksWithVisitorWrapper = runChecksWithVisitorWrapper;
39
38
  exports.lintFiles = lintFiles;
40
39
  exports.lintFilesParallel = lintFilesParallel;
41
40
  exports.applyFixes = applyFixes;
@@ -60,6 +59,7 @@ const error_handling_1 = require("./checks/error-handling");
60
59
  const global_naming_1 = require("./checks/global-naming");
61
60
  const extra_parens_1 = require("./checks/extra-parens");
62
61
  const arg_count_1 = require("./checks/arg-count");
62
+ const builtin_arg_count_1 = require("./checks/builtin-arg-count");
63
63
  const strcat_usage_1 = require("./checks/strcat-usage");
64
64
  const cond_simplify_1 = require("./checks/cond-simplify");
65
65
  const quote_style_1 = require("./checks/quote-style");
@@ -100,12 +100,17 @@ function runChecks(content, file, config) {
100
100
  const severity = checks[rule];
101
101
  if (!severity || severity === 'off')
102
102
  return;
103
- const results = fn();
104
- for (const r of results) {
105
- if (!(0, disable_1.isDisabled)(r.rule, r.line, disableMap)) {
106
- issues.push(r);
103
+ try {
104
+ const results = fn();
105
+ for (const r of results) {
106
+ if (!(0, disable_1.isDisabled)(r.rule, r.line, disableMap)) {
107
+ issues.push(r);
108
+ }
107
109
  }
108
110
  }
111
+ catch {
112
+ // Check failed, continue with remaining checks
113
+ }
109
114
  }
110
115
  function addIssues(ruleIssues) {
111
116
  for (const r of ruleIssues) {
@@ -133,6 +138,7 @@ function runChecks(content, file, config) {
133
138
  addIfEnabled('global_naming', () => (0, global_naming_1.checkGlobalNaming)(content, file));
134
139
  addIfEnabled('extra_parens', () => (0, extra_parens_1.checkExtraParens)(content, file));
135
140
  addIfEnabled('arg_count', () => (0, arg_count_1.checkArgCount)(content, file));
141
+ addIfEnabled('builtin_arg_count', () => (0, builtin_arg_count_1.checkBuiltinArgCount)(content, file));
136
142
  addIfEnabled('strcat_usage', () => (0, strcat_usage_1.checkStrcatUsage)(content, file));
137
143
  addIfEnabled('cond_simplify', () => (0, cond_simplify_1.checkCondSimplify)(content, file));
138
144
  addIfEnabled('quote_style', () => (0, quote_style_1.checkQuoteStyle)(content, file));
@@ -173,17 +179,17 @@ function runChecks(content, file, config) {
173
179
  ]);
174
180
  const needsAst = Array.from(astRules).some(r => checks[r] !== 'off');
175
181
  if (needsAst) {
176
- const ast = (0, parser_1.parseAst)(content);
177
- const visitorIssues = (0, visitor_runner_1.runChecksWithVisitor)(ast, file, config, disableMap);
178
- addIssues(visitorIssues);
182
+ try {
183
+ const ast = (0, parser_1.parseAst)(content, { errorRecovery: true });
184
+ const visitorIssues = (0, visitor_runner_1.runChecksWithVisitor)(ast, file, config, disableMap);
185
+ addIssues(visitorIssues);
186
+ }
187
+ catch {
188
+ // AST-based checks are skipped, text-based checks above still report issues
189
+ }
179
190
  }
180
191
  return issues;
181
192
  }
182
- function runChecksWithVisitorWrapper(content, file, config) {
183
- const disableMap = (0, disable_1.parseDisableComments)(content);
184
- const ast = (0, parser_1.parseAst)(content);
185
- return (0, visitor_runner_1.runChecksWithVisitor)(ast, file, config, disableMap);
186
- }
187
193
  function lintFiles(files, config, rootDir) {
188
194
  (0, locale_1.setLocale)(config.locale || 'zh');
189
195
  const allIssues = [];
@@ -321,6 +327,7 @@ exports.FIXABLE_RULES = new Set([
321
327
  ]);
322
328
  function applyFixes(issues, content, filepath) {
323
329
  const lines = content.split('\n');
330
+ const fixedLines = new Set();
324
331
  const fixesByRule = new Map();
325
332
  for (const iss of issues) {
326
333
  if (iss.file !== filepath)
@@ -330,7 +337,6 @@ function applyFixes(issues, content, filepath) {
330
337
  fixesByRule.set(iss.rule, set);
331
338
  }
332
339
  const fixableRules = exports.FIXABLE_RULES;
333
- let result = content;
334
340
  for (const [rule, lineSet] of fixesByRule) {
335
341
  if (!fixableRules.has(rule))
336
342
  continue;
@@ -339,30 +345,38 @@ function applyFixes(issues, content, filepath) {
339
345
  const idx = line - 1;
340
346
  if (idx < 0 || idx >= lines.length)
341
347
  continue;
342
- const lineContent = result.split('\n')[idx];
348
+ const lineContent = lines[idx];
343
349
  switch (rule) {
344
350
  case 'redundant_quotes': {
345
351
  const fixed = lineContent.replace(/''(\S)/g, "'$1");
346
- if (fixed !== lineContent)
347
- result = replaceLine(result, idx, fixed);
352
+ if (fixed !== lineContent) {
353
+ lines[idx] = fixed;
354
+ fixedLines.add(idx);
355
+ }
348
356
  break;
349
357
  }
350
358
  case 'double_not': {
351
359
  const fixed = lineContent.replace(/\(not\s+\(not\s+/g, '(not ');
352
- if (fixed !== lineContent)
353
- result = replaceLine(result, idx, fixed);
360
+ if (fixed !== lineContent) {
361
+ lines[idx] = fixed;
362
+ fixedLines.add(idx);
363
+ }
354
364
  break;
355
365
  }
356
366
  case 'redundant_nil_else': {
357
367
  const fixed = lineContent.replace(/\s+nil\s*\)$/, ')');
358
- if (fixed !== lineContent)
359
- result = replaceLine(result, idx, fixed);
368
+ if (fixed !== lineContent) {
369
+ lines[idx] = fixed;
370
+ fixedLines.add(idx);
371
+ }
360
372
  break;
361
373
  }
362
374
  case 'single_arg_and_or': {
363
375
  const m = lineContent.match(/\((and|or)\s+([^)\s]+)\s*\)/);
364
- if (m)
365
- result = replaceLine(result, idx, m[2]);
376
+ if (m) {
377
+ lines[idx] = m[2];
378
+ fixedLines.add(idx);
379
+ }
366
380
  break;
367
381
  }
368
382
  case 'redundant_progn': {
@@ -374,16 +388,20 @@ function applyFixes(issues, content, filepath) {
374
388
  const inner = lineContent.slice(proIdx + 7, close);
375
389
  const rest = lineContent.slice(close + 1);
376
390
  const fixed = beforePro + inner + rest;
377
- if (fixed !== lineContent)
378
- result = replaceLine(result, idx, fixed);
391
+ if (fixed !== lineContent) {
392
+ lines[idx] = fixed;
393
+ fixedLines.add(idx);
394
+ }
379
395
  }
380
396
  }
381
397
  break;
382
398
  }
383
399
  case 'redundant_let': {
384
400
  const fixed = lineContent.replace(/\(let\s+\(\)\s*/, '(progn ');
385
- if (fixed !== lineContent)
386
- result = replaceLine(result, idx, fixed);
401
+ if (fixed !== lineContent) {
402
+ lines[idx] = fixed;
403
+ fixedLines.add(idx);
404
+ }
387
405
  break;
388
406
  }
389
407
  case 'quote_style': {
@@ -395,8 +413,10 @@ function applyFixes(issues, content, filepath) {
395
413
  const quoted = lineContent.slice(qIdx + 7, close);
396
414
  const rest = lineContent.slice(close + 1);
397
415
  const fixed = beforeQ + "'" + quoted + rest;
398
- if (fixed !== lineContent)
399
- result = replaceLine(result, idx, fixed);
416
+ if (fixed !== lineContent) {
417
+ lines[idx] = fixed;
418
+ fixedLines.add(idx);
419
+ }
400
420
  }
401
421
  }
402
422
  break;
@@ -410,8 +430,10 @@ function applyFixes(issues, content, filepath) {
410
430
  const inner = lineContent.slice(pIdx + 7, close);
411
431
  const rest = lineContent.slice(close + 1);
412
432
  const fixed = beforeP + inner + rest;
413
- if (fixed !== lineContent)
414
- result = replaceLine(result, idx, fixed);
433
+ if (fixed !== lineContent) {
434
+ lines[idx] = fixed;
435
+ fixedLines.add(idx);
436
+ }
415
437
  }
416
438
  }
417
439
  break;
@@ -436,18 +458,18 @@ function applyFixes(issues, content, filepath) {
436
458
  if (thenForm && elseForm) {
437
459
  const rest = lineContent.slice(ifClose + 1);
438
460
  const fixed = indent + '(if ' + condVar + ' ' + elseForm + ' ' + thenForm + ')' + rest;
439
- if (fixed !== lineContent)
440
- result = replaceLine(result, idx, fixed);
461
+ if (fixed !== lineContent) {
462
+ lines[idx] = fixed;
463
+ fixedLines.add(idx);
464
+ }
441
465
  }
442
466
  }
443
467
  break;
444
468
  }
445
469
  case 'redundant_setq': {
446
- const allLines = result.split('\n');
447
- const trimmed = allLines[idx].trim();
470
+ const trimmed = lines[idx].trim();
448
471
  if (/^\(setq\s+(\S+)\s+\1\s*\)$/.test(trimmed)) {
449
- allLines.splice(idx, 1);
450
- result = allLines.join('\n');
472
+ lines.splice(idx, 1);
451
473
  }
452
474
  break;
453
475
  }
@@ -456,12 +478,15 @@ function applyFixes(issues, content, filepath) {
456
478
  if (fixed !== lineContent) {
457
479
  const merged = lineContent.replace(/^\(\s*setq\s+/, '(setq ');
458
480
  if (merged.includes('setq') && !merged.match(/\)\(/)) {
459
- result = replaceLine(result, idx, merged);
481
+ lines[idx] = merged;
482
+ fixedLines.add(idx);
460
483
  }
461
484
  else {
462
485
  const simplified = lineContent.replace(/\)\(setq\s+/g, '\n');
463
- if (simplified !== lineContent)
464
- result = replaceLine(result, idx, simplified);
486
+ if (simplified !== lineContent) {
487
+ lines[idx] = simplified;
488
+ fixedLines.add(idx);
489
+ }
465
490
  }
466
491
  }
467
492
  break;
@@ -475,8 +500,10 @@ function applyFixes(issues, content, filepath) {
475
500
  const listMatch = inner.match(/^\(list\s+(.*)\)\s*$/);
476
501
  if (listMatch) {
477
502
  const fixed = lineContent.slice(0, aIdx) + '(cons ' + listMatch[1] + ')' + lineContent.slice(close + 1);
478
- if (fixed !== lineContent)
479
- result = replaceLine(result, idx, fixed);
503
+ if (fixed !== lineContent) {
504
+ lines[idx] = fixed;
505
+ fixedLines.add(idx);
506
+ }
480
507
  }
481
508
  }
482
509
  }
@@ -484,40 +511,48 @@ function applyFixes(issues, content, filepath) {
484
511
  }
485
512
  case 'nth_usage': {
486
513
  const fixed = lineContent.replace(/\(nth\s+0\s+/g, '(car ');
487
- if (fixed !== lineContent)
488
- result = replaceLine(result, idx, fixed);
514
+ if (fixed !== lineContent) {
515
+ lines[idx] = fixed;
516
+ fixedLines.add(idx);
517
+ }
489
518
  break;
490
519
  }
491
520
  case 'setq_single_arg': {
492
- const allLines = result.split('\n');
493
- if (/^\s*\(setq\s+\S+\s*\)\s*$/.test(allLines[idx])) {
494
- allLines.splice(idx, 1);
495
- result = allLines.join('\n');
521
+ if (/^\s*\(setq\s+\S+\s*\)\s*$/.test(lines[idx])) {
522
+ lines.splice(idx, 1);
496
523
  }
497
524
  break;
498
525
  }
499
526
  case 'extra_parens': {
500
527
  const fixed = lineContent.replace(/\){2,}/g, ')');
501
- if (fixed !== lineContent)
502
- result = replaceLine(result, idx, fixed);
528
+ if (fixed !== lineContent) {
529
+ lines[idx] = fixed;
530
+ fixedLines.add(idx);
531
+ }
503
532
  break;
504
533
  }
505
534
  case 'empty_branch': {
506
535
  const fixed = lineContent.replace(/\(if\s+\S+\s*\)/g, m => m.slice(0, -1) + ' nil)');
507
- if (fixed !== lineContent)
508
- result = replaceLine(result, idx, fixed);
536
+ if (fixed !== lineContent) {
537
+ lines[idx] = fixed;
538
+ fixedLines.add(idx);
539
+ }
509
540
  break;
510
541
  }
511
542
  case 'comment_style': {
512
543
  const fixed = lineContent.replace(/^(\s*;)([^ ;|].*)$/gm, '$1 $2');
513
- if (fixed !== lineContent)
514
- result = replaceLine(result, idx, fixed);
544
+ if (fixed !== lineContent) {
545
+ lines[idx] = fixed;
546
+ fixedLines.add(idx);
547
+ }
515
548
  break;
516
549
  }
517
550
  case 'eq_usage': {
518
551
  const fixed = lineContent.replace(/\(eq\s+(\S+)\s+(\d+)\s*\)/g, '(= $1 $2)');
519
- if (fixed !== lineContent)
520
- result = replaceLine(result, idx, fixed);
552
+ if (fixed !== lineContent) {
553
+ lines[idx] = fixed;
554
+ fixedLines.add(idx);
555
+ }
521
556
  break;
522
557
  }
523
558
  case 'cond_simplify': {
@@ -538,8 +573,10 @@ function applyFixes(issues, content, filepath) {
538
573
  const bodyExpr = branchContent.slice(space).trim();
539
574
  const rest = lineContent.slice(condEnd + 1);
540
575
  const fixed = indent + '(if ' + testExpr + ' ' + bodyExpr + ')' + rest;
541
- if (fixed !== lineContent)
542
- result = replaceLine(result, idx, fixed);
576
+ if (fixed !== lineContent) {
577
+ lines[idx] = fixed;
578
+ fixedLines.add(idx);
579
+ }
543
580
  }
544
581
  }
545
582
  }
@@ -549,34 +586,31 @@ function applyFixes(issues, content, filepath) {
549
586
  }
550
587
  case 'self_compare': {
551
588
  const fixed = lineContent.replace(/\((?:[=/<>]+|eq|equal)\s+(\S+)\s+\1\s*\)/g, 'T');
552
- if (fixed !== lineContent)
553
- result = replaceLine(result, idx, fixed);
589
+ if (fixed !== lineContent) {
590
+ lines[idx] = fixed;
591
+ fixedLines.add(idx);
592
+ }
554
593
  break;
555
594
  }
556
595
  case 'while_constant': {
557
- const allLines = result.split('\n');
558
- const trimmed = allLines[idx].trim();
596
+ const trimmed = lines[idx].trim();
559
597
  const nilMatch = trimmed.match(/^\(\s*while\s+nil\s+(.*)\)\s*$/);
560
598
  if (nilMatch) {
561
- allLines[idx] = allLines[idx].replace(trimmed, 'nil');
562
- result = allLines.join('\n');
599
+ lines[idx] = lines[idx].replace(trimmed, 'nil');
563
600
  }
564
601
  break;
565
602
  }
566
603
  case 'redundant_list': {
567
604
  const fixed = lineContent.replace(/\(\s*list\s*\)/g, 'nil');
568
- if (fixed !== lineContent)
569
- result = replaceLine(result, idx, fixed);
605
+ if (fixed !== lineContent) {
606
+ lines[idx] = fixed;
607
+ fixedLines.add(idx);
608
+ }
570
609
  break;
571
610
  }
572
611
  }
573
612
  }
574
613
  }
575
- return result;
576
- }
577
- function replaceLine(content, lineIdx, newLine) {
578
- const lines = content.split('\n');
579
- lines[lineIdx] = newLine;
580
614
  return lines.join('\n');
581
615
  }
582
616
  function parseIgnoreFile(rootDir) {
@@ -593,23 +627,51 @@ const UTF8_BOM = 0xfeff;
593
627
  function fixFile(filepath) {
594
628
  const fixes = [];
595
629
  let content = fs.readFileSync(filepath, 'utf-8');
596
- const wsFixed = content
597
- .split('\n')
598
- .map(l => l.replace(/[ \t]+$/, ''))
599
- .join('\n');
600
- if (wsFixed !== content) {
601
- content = wsFixed;
602
- fixes.push('trailing_whitespace');
603
- }
630
+ // 1. Remove BOM
604
631
  if (content.charCodeAt(0) === UTF8_BOM) {
605
632
  content = content.slice(1);
606
633
  fixes.push('encoding (BOM)');
607
634
  }
635
+ // 2. Single line pass: trailing whitespace + empty comment lines
636
+ const origLines = content.split('\n');
637
+ let wsChanged = false;
638
+ let ecChanged = false;
639
+ const processed = origLines.map(l => {
640
+ const stripped = l.replace(/[ \t]+$/, '');
641
+ if (stripped !== l)
642
+ wsChanged = true;
643
+ if (/^\s*;\s*$/.test(stripped)) {
644
+ ecChanged = true;
645
+ return '';
646
+ }
647
+ return stripped;
648
+ });
649
+ if (wsChanged)
650
+ fixes.push('trailing_whitespace');
651
+ if (ecChanged)
652
+ fixes.push('empty_comment');
653
+ if (wsChanged || ecChanged)
654
+ content = processed.join('\n');
655
+ // 3. Count parens (string/comment aware), fix trailing excess
608
656
  let openCount = 0;
609
657
  let closeCount = 0;
610
- let fixContent = content;
611
- for (let i = 0; i < fixContent.length; i++) {
612
- const ch = fixContent[i];
658
+ let inStr = false;
659
+ for (let i = 0; i < content.length; i++) {
660
+ const ch = content[i];
661
+ if (ch === '"') {
662
+ inStr = !inStr;
663
+ continue;
664
+ }
665
+ if (inStr) {
666
+ if (ch === '\\')
667
+ i++;
668
+ continue;
669
+ }
670
+ if (ch === ';') {
671
+ const nl = content.indexOf('\n', i);
672
+ i = nl !== -1 ? nl : content.length;
673
+ continue;
674
+ }
613
675
  if (ch === '(')
614
676
  openCount++;
615
677
  else if (ch === ')')
@@ -617,29 +679,17 @@ function fixFile(filepath) {
617
679
  }
618
680
  if (closeCount > openCount) {
619
681
  let excess = closeCount - openCount;
620
- while (excess > 0 && fixContent.endsWith(')')) {
621
- fixContent = fixContent.slice(0, -1);
682
+ let fixed = content;
683
+ while (excess > 0 && fixed.endsWith(')')) {
684
+ fixed = fixed.slice(0, -1);
622
685
  excess--;
623
686
  }
624
- fixContent = fixContent.replace(/\n[ \t]*$/, '');
625
- if (fixContent !== content) {
626
- content = fixContent;
687
+ fixed = fixed.replace(/\n[ \t]*$/, '');
688
+ if (fixed !== content) {
689
+ content = fixed;
627
690
  fixes.push('trailing_paren');
628
691
  }
629
692
  }
630
- const lines = content.split('\n');
631
- let changed = false;
632
- const fixedLines = lines.map(l => {
633
- if (/^\s*;\s*$/.test(l)) {
634
- changed = true;
635
- return '';
636
- }
637
- return l;
638
- });
639
- if (changed) {
640
- content = fixedLines.join('\n');
641
- fixes.push('empty_comment');
642
- }
643
693
  if (fixes.length > 0) {
644
694
  fs.writeFileSync(filepath, content, 'utf-8');
645
695
  }
@@ -0,0 +1,41 @@
1
+ ((AUTOLISP ())
2
+ (@ (COMMON-LISP AUTOLISP))
3
+ (C ())
4
+ (JSON ())
5
+ (SIDEBAR ())
6
+ (FUN ())
7
+ (DCL ())
8
+ (BASE ())
9
+ (STRING ())
10
+ (BLOCK ())
11
+ (ENTITY ())
12
+ (LAYER ())
13
+ (LAYOUT ())
14
+ (CURVE ())
15
+ (LIST ())
16
+ (M ())
17
+ (P ())
18
+ (UI ())
19
+ (SYS ())
20
+ (EXCEL ())
21
+ (WORD ())
22
+ (RE ())
23
+ (VECTRA ())
24
+ (DOS ())
25
+ (AT-PM ())
26
+ (QRENCODE ())
27
+ (NETWORK ())
28
+ (PKGMAN ())
29
+ (DATETIME ())
30
+ (DICT ())
31
+ (@NLP ())
32
+ (AT-SIDEBAR ())
33
+ (S ())
34
+ (VL ())
35
+ (VLR ())
36
+ (VLAX ())
37
+ (THEME ())
38
+ (AJAX ())
39
+ (ATLISP ())
40
+ (LOG ())
41
+ (ATLISP-CORE ()))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlisp/lint",
3
- "version": "0.1.23",
3
+ "version": "0.1.25",
4
4
  "description": "AutoLISP static analysis tool — parens, security, conventions, SBCL syntax validation",
5
5
  "keywords": [
6
6
  "CAD",
@@ -37,7 +37,7 @@
37
37
  "prepack": "npm run build"
38
38
  },
39
39
  "dependencies": {
40
- "@atlisp/parser": "^0.1.2"
40
+ "@atlisp/parser": "^0.1.3"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@types/jest": "^29",