14 Commits

Author SHA1 Message Date
f085882a4a Clean up compiler self-lint warnings 2026-04-04 16:42:51 +02:00
8488cab0ac Make surface rules token-aware 2026-04-04 16:11:46 +02:00
bd89fb476e Improve diagnostics and Guile corpus handling 2026-04-04 15:54:51 +02:00
6dc717186e Expand test suite: 84 → 139 tests covering all bugfixes
New test files:
- test-config.scm (15 tests): find-config directory walking,
  load-config with explicit/missing/auto-discovery paths,
  merge-configs override semantics, generate-template pretty-print
  output validity.

- test-engine.scm (40 tests): filter-rules-by-config with
  enable/disable/combined, severity>=? helper, lint-file with
  --pass surface (no compile errors leak), severity filtering
  (info excluded at warning level), rule disabling via config.

  Fix mode tests: trailing-whitespace fix, comment-semicolons
  fix (single ; → ;;), no-tabs fix (8-space expansion),
  tab-stop alignment, blank-lines deletion, fix composition
  (tabs + trailing whitespace on same line), idempotency
  (second pass changes nothing), multi-pass convergence
  (3-way conflict: tabs + trailing + comment on same line
  converges in 2 passes).

  Compile-error formatting: no raw ~S/~A format specifiers
  in error messages, module name present in output.

  Integration: lint-files with %fix mode applies fixes and
  returns 0 unfixed count.
2026-04-04 14:14:30 +02:00
78f3f7e6d3 Auto-fix all surface issues: tabs, blank-lines, fix composition
New auto-fixes:
- no-tabs: expand tabs to 8-space tab stops, also trim trailing
  whitespace to avoid conflicts with trailing-whitespace fix
- blank-lines: delete excess blank lines via delete-line fix type.
  First excess line emits a warning; subsequent excess lines emit
  info-level 'blank-lines-fixup' diagnostics (hidden at --severity
  warning) with delete-line fixes.

Fix engine improvements:
- apply-fixes-to-file now supports delete-line (sentinel-based skip)
- When multiple replace-line fixes target the same line (e.g. both
  trailing-whitespace and no-tabs), the replacement with the greatest
  edit distance from the original is chosen, avoiding conflicts where
  one fix would overwrite another.

Result on Guix tree (1336 files):
  gulie --pass surface --config .gulie.sexp --fix refs/guix/
  → Fixed 2007 issues.
  → 0 remaining warnings.
  → Single pass, idempotent, files parse correctly.
2026-04-04 14:08:44 +02:00
412814ff72 Implement --fix mode and add Guix-tuned config
--fix mode:
- apply-fixes-to-file collects fixable diagnostics, applies
  replace-line fixes bottom-up via a vector, writes file back
- lint-files in fix mode applies fixes then reports only unfixed
  diagnostics; prints fix count to stderr
- Idempotent: second run finds nothing to fix

Fix records added:
- trailing-whitespace already had fix records
- comment-semicolons now produces fix records for both
  single-; on own line (→ ;;) and ;;;+ inline (→ ;;)

Guix config (refs/guix/.gulie.sexp):
- Surface pass only (semantic pass useless without Guix on load path)
- line-length disabled (URLs, hashes, descriptions)
- Remaining rules: trailing-whitespace, no-tabs, comment-semicolons,
  blank-lines

On Guix tree: 2005 findings → 594 after --fix (1411 auto-fixed).
Remaining: 523 no-tabs (real tabs) + 71 blank-lines (real).
2026-04-04 14:02:18 +02:00
f5d5919943 Parallelize file linting with n-par-map
Use Guile's n-par-map from (ice-9 threads) to lint files in parallel,
one thread per CPU core. Results are collected per-file then output
sequentially to maintain deterministic ordering.

Performance on Guix tree (1336 files, 12 cores):

  Before (sequential)     After (parallel)
  full:    21s             full:    14s   (1.5x)
  surface: 15s             surface:  8s   (1.9x)
  line:    14s             line:     7s   (2.0x)
2026-04-04 13:51:25 +02:00
1734ebe381 Skip tokenizer/CST parsing when no CST rules are active
Check filter-rules-by-config before invoking the tokenizer in
lint-file. When all CST rules are disabled (e.g. --disable
comment-semicolons), the expensive tokenize+parse-cst pass is
skipped entirely.

On the Guix tree (1336 files), this saves ~2s on surface-only
runs (15.6s → 13.7s). The savings are more pronounced on
projects with fewer monster files.
2026-04-04 13:44:31 +02:00
f979d48e54 Fix 8 bugs found by running gulie on the Guix source tree
Bug 1: Config auto-discovery — load-config now walks CWD and parent
directories for .gulie.sexp when no --config is given, matching the
documented behavior. Added find-config helper.

Bug 2: Compile-error messages garbled — the catch handler now properly
destructures Guile exception args (subr fmt fmt-args . _) and uses
apply+format instead of raw display, producing readable messages like
"no code for module (guix licenses)" instead of
"#f no code for module ~S ((guix licenses)) #f".

Bug 3: --init template unreadable — generate-template now uses
pretty-print instead of write, producing properly indented output.

Bug 4: CLI options silently ignored — --pass, --disable, --rule, and
--severity are now wired up in main and threaded into config as %pass,
augmented disable list, enable list, and %min-severity respectively.

Bug 5: enable/disable config keys never consulted — added
filter-rules-by-config, used in run-line-rules and run-cst-rules.

Bug 6: blank-lines rule spammed one diagnostic per excess line —
changed trigger to fire once per group at the boundary.

Bug 7: read-file-to-string slow — replaced line-by-line accumulation
with get-string-all.

Bug 8: No way to skip semantic pass — lint-file now respects %pass
config key (surface/semantic/all) and %min-severity for filtering.
2026-04-04 13:30:48 +02:00
e3e28a911a docs: License 2026-04-02 00:26:05 +02:00
f512e0aced style: Dog fooding 2026-04-02 00:20:24 +02:00
98fbba03cb build: Line length default 2026-04-02 00:20:09 +02:00
1e85dd224a build: Nix package 2026-04-01 23:55:07 +02:00
d0115672dd First iteration 2026-04-01 23:35:50 +02:00