starting new job...
→ running command: dir='/etc/byggsteg/job-clone//sift/trunk'
branch='trunk'
if ! command -v git >/dev/null 2>&1; then
echo 'byggsteg: git is not on this deployment PATH, so the clone cannot be updated' >&2
exit 1
fi
if ! cd "$dir"; then
echo "byggsteg: cannot enter the clone $dir" >&2
exit 1
fi
root=$(git rev-parse --show-toplevel 2>/dev/null)
if [ "$root" != "$(pwd -P)" ]; then
echo "byggsteg: $dir is not a git checkout; remove it and the next run clones it again" >&2
exit 1
fi
if ! origin=$(git remote get-url origin 2>/dev/null); then
echo "byggsteg: $dir has no origin remote to fetch $branch from" >&2
exit 1
fi
before=$(git rev-parse --short HEAD 2>/dev/null) || before=none
attempt=1
while :; do
if GIT_TERMINAL_PROMPT=0 git fetch --quiet origin "+refs/heads/$branch:refs/remotes/origin/$branch"; then
break
fi
if [ "$attempt" -ge 3 ]; then
echo "byggsteg: could not fetch $branch from $origin after 3 attempts; is the branch still there, and is the remote reachable?" >&2
exit 1
fi
echo "byggsteg: fetching $branch from $origin failed; retrying in $((attempt * 2))s" >&2
sleep $((attempt * 2))
attempt=$((attempt + 1))
done
if ! git checkout --quiet --force -B "$branch" FETCH_HEAD; then
echo "byggsteg: fetched $branch from $origin but could not check it out" >&2
exit 1
fi
after=$(git rev-parse --short HEAD)
if [ "$before" = "$after" ]; then
echo "byggsteg: $branch was already at $after"
else
echo "byggsteg: $branch moved from $before to $after"
fi
byggsteg: trunk moved from f4dc050 to b8802ca
→ running command: cd /etc/byggsteg/job-clone/sift/trunk && uname -a
Linux wolk-jjba 7.2.11-gnu #1 SMP PREEMPT_DYNAMIC 1 x86_64 GNU/Linux
→ running command: cd /etc/byggsteg/job-clone/sift/trunk && git log --name-status HEAD^..HEAD
commit b8802ca0cdc90a260376a067ceffe2a5c34c88db
Author: Josep Bigorra <jjbigorra@gmail.com>
Date: Tue Nov 3 10:44:56 2026 +0100
chore(release): v1.21.0
M .github/workflows/sift.yml
M .pre-commit-hooks.yaml
M README.org
M action.yml
M doc/editors.org
M doc/language-server.org
M doc/rules.org
M editors/vscode/package.json
M emacs/sift.el
M src/sift/analysis.scm
M src/sift/definitions.scm
M src/sift/lsp.scm
M src/sift/records.scm
M tests/lsp.scm
→ running command: cd /etc/byggsteg/job-clone/sift/trunk && maak test
channels.scm:17:6: warning: channel 'jointhefreeworld' is not trusted
loading tests/catalogue.scm
;;; note: source file ./src/sift/records.scm
;;; newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/records.go
;;; note: source file ./src/sift/records.scm
;;; newer than compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/records.scm.go
;;; note: auto-compilation is enabled, set GUILE_AUTO_COMPILE=0
;;; or pass the --no-auto-compile argument to disable.
;;; compiling ./src/sift/records.scm
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/records.scm.go
;;; note: source file ./src/sift/lint.scm
;;; newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/lint.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/lint.scm.go
;;; note: source file ./src/sift/reader.scm
;;; newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/reader.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/reader.scm.go
;;; note: source file ./src/sift/pool.scm
;;; newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/pool.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/pool.scm.go
;;; note: source file ./src/sift/check/base.scm
;;; newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/check/base.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/check/base.scm.go
;;; note: source file ./src/sift/checkers/whitespace.scm
;;; newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/checkers/whitespace.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/checkers/whitespace.scm.go
;;; note: source file ./src/sift/checkers/comments.scm
;;; newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/checkers/comments.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/checkers/comments.scm.go
;;; note: source file ./src/sift/checkers/parens.scm
;;; newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/checkers/parens.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/checkers/parens.scm.go
;;; note: source file ./src/sift/checkers/bodies.scm
;;; newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/checkers/bodies.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/checkers/bodies.scm.go
;;; note: source file ./src/sift/checkers/scheme.scm
;;; newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/checkers/scheme.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/checkers/scheme.scm.go
;;; note: source file ./src/sift/format.scm
;;; newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/format.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/format.scm.go
;;; note: source file ./src/sift/imports.scm
;;; newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/imports.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/imports.scm.go
;;; note: source file ./src/sift/checkers/elisp.scm
;;; newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/checkers/elisp.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/checkers/elisp.scm.go
;;; note: source file ./src/sift/checkers/cl.scm
;;; newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/checkers/cl.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/checkers/cl.scm.go
;;; note: source file ./src/sift/checkers/ergonomics.scm
;;; newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/checkers/ergonomics.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/checkers/ergonomics.scm.go
;;; note: source file ./src/sift/checkers/naming.scm
;;; newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/checkers/naming.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/checkers/naming.scm.go
;;; note: source file ./src/sift/checkers/simplify.scm
;;; newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/checkers/simplify.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/checkers/simplify.scm.go
;;; note: source file ./src/sift/checkers/sxml.scm
;;; newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/checkers/sxml.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/checkers/sxml.scm.go
;;; note: source file ./src/sift/checkers/practices.scm
;;; newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/checkers/practices.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/checkers/practices.scm.go
;;; note: source file ./src/sift/definitions.scm
;;; newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/definitions.go
;;; note: source file ./src/sift/definitions.scm
;;; newer than compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/definitions.scm.go
;;; compiling ./src/sift/definitions.scm
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/definitions.scm.go
;;; note: source file ./src/sift/catalogue.scm
;;; newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/catalogue.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/catalogue.scm.go
;;; note: source file ./src/sift/config.scm
;;; newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/config.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/config.scm.go
;;; note: source file ./src/sift/yaml.scm
;;; newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/yaml.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/yaml.scm.go
loading tests/check-base.scm
loading tests/checkers/append-nothing.scm
loading tests/checkers/apply-of-list.scm
loading tests/checkers/assoc-ref-outputs.scm
loading tests/checkers/beta-reduction.scm
loading tests/checkers/blank-line-in-body.scm
loading tests/checkers/call-arity.scm
loading tests/checkers/case-literal-datum.scm
loading tests/checkers/checkdoc-style-verb.scm
loading tests/checkers/clause-brackets.scm
loading tests/checkers/comment-semicolons.scm
loading tests/checkers/composition.scm
loading tests/checkers/dangling-paren.scm
loading tests/checkers/declare-indent.scm
loading tests/checkers/defpackage-use.scm
loading tests/checkers/defun-no-docstring.scm
loading tests/checkers/docstring-arguments.scm
loading tests/checkers/docstring-first-line.scm
loading tests/checkers/docstring-indent.scm
loading tests/checkers/docstring-missing.scm
loading tests/checkers/docstring-texinfo.scm
loading tests/checkers/double-colon.scm
loading tests/checkers/ecase-otherwise.scm
loading tests/checkers/empty-body.scm
loading tests/checkers/empty-form.scm
loading tests/checkers/eq-nil.scm
loading tests/checkers/eq-non-symbol.scm
loading tests/checkers/eta-reduction.scm
loading tests/checkers/gexp-output-script.scm
loading tests/checkers/gexp-quoted.scm
loading tests/checkers/if-without-else.scm
loading tests/checkers/inputs-label-alist.scm
loading tests/checkers/interactive-without-arguments.scm
loading tests/checkers/interactive-without-docstring.scm
loading tests/checkers/internal-define.scm
loading tests/checkers/keyword-arguments.scm
loading tests/checkers/let-sibling.scm
loading tests/checkers/let-simplification.scm
loading tests/checkers/letrec-init-reference.scm
loading tests/checkers/letrec-single-binding.scm
loading tests/checkers/lexical-binding-missing.scm
loading tests/checkers/library-not-found.scm
loading tests/checkers/line-length.scm
loading tests/checkers/loop-keyword-style.scm
loading tests/checkers/mixed-lambda-list.scm
loading tests/checkers/naming-convention.scm
loading tests/checkers/needless-let-star.scm
loading tests/checkers/negated-if.scm
loading tests/checkers/nesting-depth.scm
loading tests/checkers/number-literal-argument.scm
loading tests/checkers/package-description-literal.scm
loading tests/checkers/package-prefix.scm
loading tests/checkers/package-synopsis.scm
loading tests/checkers/phase-name-quoting.scm
loading tests/checkers/practices.scm
loading tests/checkers/predicate-name.scm
loading tests/checkers/provide-missing.scm
loading tests/checkers/quasiquote-unquote-constant.scm
loading tests/checkers/reader-prefix-break.scm
loading tests/checkers/redundant-identity.scm
loading tests/checkers/redundant-progn.scm
loading tests/checkers/require-cl.scm
loading tests/checkers/save-excursion-set-buffer.scm
loading tests/checkers/sha256-base32.scm
loading tests/checkers/single-letter-name.scm
loading tests/checkers/special-variable-name.scm
loading tests/checkers/string-append-file-append.scm
loading tests/checkers/string-literal-argument.scm
loading tests/checkers/sxml-attributes.scm
loading tests/checkers/sxml-child.scm
loading tests/checkers/sxml-empty-element.scm
loading tests/checkers/tabs.scm
loading tests/checkers/trailing-blank-lines.scm
loading tests/checkers/trailing-whitespace.scm
loading tests/checkers/ungexp-outside-gexp.scm
loading tests/checkers/unless-without-body.scm
loading tests/checkers/unmatched-parens.scm
loading tests/checkers/unused-argument.scm
loading tests/checkers/unused-definition.scm
loading tests/checkers/unused-import-from.scm
loading tests/checkers/unused-import.scm
loading tests/checkers/use-modules-in-gexp.scm
loading tests/checkers/when-without-body.scm
loading tests/checkers/wrap-in-let.scm
loading tests/cli.scm
loading tests/declarations.scm
loading tests/definitions.scm
loading tests/files.scm
;;; note: source file ./src/sift/files.scm
;;; newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/files.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/files.scm.go
loading tests/format-cl.scm
loading tests/format-elisp.scm
loading tests/format-scheme.scm
loading tests/gexp.scm
loading tests/json.scm
;;; note: source file ./src/sift/json.scm
;;; newer than compiled /gnu/store/icvslslfgxymkb74yris4pnff2dyr8bq-profile/lib/guile/3.0/site-ccache/sift/json.go
;;; found fresh local cache at /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/json.scm.go
loading tests/lsp.scm
+----------------------------------------------+
[📑 suite] catalogue
[🧪 test] every code looks like one
✅ got: ()
[🧪 test] every rule has an example and a sentence about its fix
✅ got: ()
[🧪 test] doc/rules.org is what the rules produce
[⚙️ assert] doc/rules.org is up to date
✅ got: #t
[🧪 test] the summary table has a row per rule
✅ got: 92
[🧪 test] every rule has a code
✅ got: ()
[🧪 test] no two rules share a code
✅ got: 92
[🧪 test] the document names every rule by name and code
✅ got: ** SIFT068 append-nothing
✅ got: ** SIFT064 apply-of-list
✅ got: ** SIFT080 assoc-ref-outputs
✅ got: ** SIFT046 beta-reduction
✅ got: ** SIFT052 blank-line-in-body
✅ got: ** SIFT088 call-arity
✅ got: ** SIFT069 case-literal-datum
✅ got: ** SIFT022 checkdoc-style-verb
✅ got: ** SIFT036 clause-brackets
✅ got: ** SIFT051 comment-semicolons
✅ got: ** SIFT047 composition
✅ got: ** SIFT056 cond-else-not-last
✅ got: ** SIFT027 dangling-paren
✅ got: ** SIFT024 declare-indent
✅ got: ** SIFT059 defcustom-without-type
✅ got: ** SIFT071 defpackage-use
✅ got: ** SIFT028 defun-no-docstring
✅ got: ** SIFT034 docstring-arguments
✅ got: ** SIFT038 docstring-before-interactive
✅ got: ** SIFT018 docstring-first-line
✅ got: ** SIFT019 docstring-indent
✅ got: ** SIFT017 docstring-missing
✅ got: ** SIFT035 docstring-texinfo
✅ got: ** SIFT026 double-colon
✅ got: ** SIFT037 duplicate-binding
✅ got: ** SIFT057 duplicate-case-datum
✅ got: ** SIFT009 duplicate-keyword
✅ got: ** SIFT072 ecase-otherwise
✅ got: ** SIFT005 empty-body
✅ got: ** SIFT008 empty-form
✅ got: ** SIFT067 eq-nil
✅ got: ** SIFT092 eq-non-symbol
✅ got: ** SIFT055 eq-on-literal
✅ got: ** SIFT045 eta-reduction
✅ got: ** SIFT079 gexp-output-script
✅ got: ** SIFT077 gexp-quoted
✅ got: ** SIFT012 if-without-else
✅ got: ** SIFT087 inputs-label-alist
✅ got: ** SIFT076 interactive-without-arguments
✅ got: ** SIFT021 interactive-without-docstring
✅ got: ** SIFT011 internal-define
✅ got: ** SIFT032 keyword-arguments
✅ got: ** SIFT065 let-sibling
✅ got: ** SIFT048 let-simplification
✅ got: ** SIFT070 letrec-init-reference
✅ got: ** SIFT015 letrec-single-binding
✅ got: ** SIFT020 lexical-binding-missing
✅ got: ** SIFT061 library-not-found
✅ got: ** SIFT003 line-length
✅ got: ** SIFT029 loop-keyword-style
✅ got: ** SIFT073 mixed-lambda-list
✅ got: ** SIFT040 naming-convention
✅ got: ** SIFT066 needless-let*
✅ got: ** SIFT033 negated-if
✅ got: ** SIFT044 nesting-depth
✅ got: ** SIFT090 number-literal-argument
✅ got: ** SIFT085 package-description-literal
✅ got: ** SIFT025 package-prefix
✅ got: ** SIFT084 package-synopsis
✅ got: ** SIFT082 phase-name-quoting
✅ got: ** SIFT041 predicate-name
✅ got: ** SIFT023 provide-missing
✅ got: ** SIFT016 quasiquote-unquote-constant
✅ got: ** SIFT054 quote-of-constant
✅ got: ** SIFT007 reader-prefix-break
✅ got: ** SIFT030 redundant-identity
✅ got: ** SIFT006 redundant-progn
✅ got: ** SIFT074 require-cl
✅ got: ** SIFT075 save-excursion-set-buffer
✅ got: ** SIFT086 sha256-base32
✅ got: ** SIFT053 single-letter-name
✅ got: ** SIFT042 special-variable-name
✅ got: ** SIFT081 string-append-file-append
✅ got: ** SIFT089 string-literal-argument
✅ got: ** SIFT049 sxml-attributes
✅ got: ** SIFT050 sxml-child
✅ got: ** SIFT063 sxml-empty-element
✅ got: ** SIFT002 tabs
✅ got: ** SIFT058 too-many-arguments
✅ got: ** SIFT010 trailing-blank-lines
✅ got: ** SIFT001 trailing-whitespace
✅ got: ** SIFT078 ungexp-outside-gexp
✅ got: ** SIFT014 unless-without-body
✅ got: ** SIFT004 unmatched-parens
✅ got: ** SIFT043 unused-argument
✅ got: ** SIFT039 unused-binding
✅ got: ** SIFT062 unused-definition
✅ got: ** SIFT060 unused-import
✅ got: ** SIFT091 unused-import-from
✅ got: ** SIFT083 use-modules-in-gexp
✅ got: ** SIFT013 when-without-body
✅ got: ** SIFT031 wrap-in-let
+----------------------------------------------+
[📑 suite] walk: where code is evaluated
[🧪 test] a quoted form holds data, not code
[⚙️ assert] only the call is a form
✅ got: (#t #f #f)
[⚙️ assert] the call, `car`, and the quote mark
✅ got: 3
[🧪 test] nothing inside a vector literal is code
[⚙️ assert] the two calls, and neither literal
✅ got: (begin f)
[🧪 test] a `case` datum is data, and its clauses are code
[⚙️ assert] the `case`, and the calls in the clause bodies
✅ got: (case f else g)
[🧪 test] an unquote is code again
[⚙️ assert] the two forms inside unquotes, and nothing else
✅ got: (if list)
[🧪 test] `walk-forms' and `code-position?' agree on every ambiguous source
[⚙️ assert] "(quote (if a b))\n" agrees
✅ got: #t
[⚙️ assert] "'(if a b)\n" agrees
✅ got: #t
[⚙️ assert] "`(a ,(if b c) d)\n" agrees
✅ got: #t
[⚙️ assert] "`(a ,@(if b (list c)) d)\n" agrees
✅ got: #t
[⚙️ assert] "(case x\n ((if a b) 1)\n (else (if a b)))\n" agrees
✅ got: #t
[⚙️ assert] "(define (f (if #f)) (if a b))\n" agrees
✅ got: #t
[⚙️ assert] "(lambda (x) (lambda (y) y))\n" agrees
✅ got: #t
[⚙️ assert] "#(if a b)\n" agrees
✅ got: #t
[⚙️ assert] "#u8(1 2 3)\n" agrees
✅ got: #t
[⚙️ assert] "(define x #(1 #(2 (if a b))))\n" agrees
✅ got: #t
[⚙️ assert] "(let loop ((i 0)) (when (< i 1) (loop (+ i 1))))\n" agrees
✅ got: #t
[⚙️ assert] "(define-syntax m (syntax-rules () ((_ a) a)))\n" agrees
✅ got: #t
[⚙️ assert] "#'(a b)\n" agrees
✅ got: #t
[⚙️ assert] "(syntax-case stx ()\n ((_ a) #'a))\n" agrees
✅ got: #t
[⚙️ assert] "(case x\n ((a b) 1)\n (else 2))\n" agrees
✅ got: #t
[⚙️ assert] "(defun f (x) \"doc\" (if x y z))\n" agrees
✅ got: #t
[⚙️ assert] "(defmacro m (a) `(list ,a))\n" agrees
✅ got: #t
[⚙️ assert] "#+foo (if a b)\n" agrees
✅ got: #t
[⚙️ assert] "(quasiquote (a (unquote (if x y))))\n" agrees
✅ got: #t
[⚙️ assert] "; a comment\n(if a b)\n" agrees
✅ got: #t
[🧪 test] a parameter list holds parameters, not forms
[⚙️ assert] the definition and the call, not the default's `g`
✅ got: (define g)
+----------------------------------------------+
[📑 suite] checker: append-nothing
[🧪 test] the fix is the other list
[⚙️ assert] the fix produces the expected text
✅ got: xs
[🧪 test] accepts an append with no empty list
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] the empty list may come first
[⚙️ assert] the fix produces the expected text
✅ got: xs
[🧪 test] the fixed files have nothing left to report
[⚙️ assert] "(append xs '())\n" is clean after its fix
✅ got: ()
[⚙️ assert] "(append '() xs)\n" is clean after its fix
✅ got: ()
[⚙️ assert] "(append '(1) '() '(2))\n" is clean after its fix
✅ got: ()
[🧪 test] reports an append of the empty list
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
[🧪 test] the empty list may sit between two others
[⚙️ assert] the fix produces the expected text
✅ got: (append '(1) '(2))
+----------------------------------------------+
[📑 suite] checker: apply-of-list
[🧪 test] reports an apply of the empty list
[⚙️ assert] the fix produces the expected text
✅ got: (f)
[🧪 test] the fix writes the call
[⚙️ assert] the fix produces the expected text
✅ got: (f 1 2 3)
[🧪 test] accepts a list argument that is not the last one
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] the fixed files have nothing left to report
[⚙️ assert] "(apply f 1 (list 2 3))\n" is clean after its fix
✅ got: ()
[⚙️ assert] "(apply f '())\n" is clean after its fix
✅ got: ()
[🧪 test] reports an apply of a list
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
[🧪 test] accepts an apply of a variable
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] an Emacs Lisp apply is the same apply
[⚙️ assert] the fix produces the expected text
✅ got: ('f 1 2)
+----------------------------------------------+
[📑 suite] checker: assoc-ref-outputs
[🧪 test] reports the alist lookup inside a gexp
[⚙️ assert] the findings are where they should be
✅ got: ((1 10))
[🧪 test] reports the alist in a quasiquoted build body
[⚙️ assert] the number of findings is right
✅ got: 1
[🧪 test] that body's fix writes `%output`
[⚙️ assert] the fix produces the expected text
✅ got: (gexp->derivation "x" `(mkdir %output))
[🧪 test] accepts `#$output`
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] the fix writes `#$output`
[⚙️ assert] the fix produces the expected text
✅ got: #~(mkdir #$output)
[⚙️ assert] the fixed text is clean
✅ got: ()
[🧪 test] accepts a lookup of a build input
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] leaves a lookup outside a build body alone
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] a quasiquote outside a derivation is an ordinary list
[⚙️ assert] the findings are where they should be
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: beta-reduction
[🧪 test] a Common Lisp lambda applied in place is a let too
[⚙️ assert] the fix produces the expected text
✅ got: (let ((x (g))) (f x))
[🧪 test] the fix writes the let
[⚙️ assert] the fix produces the expected text
✅ got: (let ((x (g))) (f x))
[🧪 test] a multi-form body becomes a multi-form let
[⚙️ assert] the fix produces the expected text
✅ got: (let ((x (h))) (f x) (g x))
[🧪 test] accepts a call to something that is not a lambda
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts a lambda with no body
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] the fixed file has nothing left to report
[⚙️ assert] the fixed text is clean
✅ got: ()
[🧪 test] reports a lambda applied in place
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
[🧪 test] accepts a lambda applied to two arguments
[⚙️ assert] the findings are where they should be
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: blank-line-in-body
[🧪 test] accepts a body whose forms are adjacent
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a blank line in a `let' body
[⚙️ assert] the findings are where they should be
✅ got: ((4 3))
[🧪 test] reports a blank line in a `lambda' body
[⚙️ assert] the findings are where they should be
✅ got: ((4 3))
[🧪 test] reports a blank line between two body forms of a definition
[⚙️ assert] the findings are where they should be
✅ got: ((4 3))
[🧪 test] accepts a blank line between top-level forms
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a run of blank lines as one finding
[⚙️ assert] the findings are where they should be
✅ got: ((5 3))
[🧪 test] accepts a blank line between two internal definitions
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts a blank line between the bindings of a `let'
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a blank line between the forms of an Emacs Lisp defun
[⚙️ assert] the findings are where they should be
✅ got: ((4 3))
+----------------------------------------------+
[📑 suite] checker: call-arity
[🧪 test] a procedure bound in a let is counted, not the top-level one
[⚙️ assert] the number of findings is right
✅ got: 1
[🧪 test] a case-lambda clause list with a gap reports the counts it takes
[⚙️ assert] the findings are where they should be
✅ got: ()
[⚙️ assert] the number of findings is right
✅ got: 1
[🧪 test] a name defined twice accepts what either definition accepts
[⚙️ assert] the findings are where they should be
✅ got: ()
[⚙️ assert] the number of findings is right
✅ got: 1
[⚙️ assert] the number of findings is right
✅ got: 1
[🧪 test] reports a call with too many arguments
[⚙️ assert] the number of findings is right
✅ got: 1
[🧪 test] a definition inside a body is the one a call in it means
[⚙️ assert] the findings are where they should be
✅ got: ()
[⚙️ assert] the number of findings is right
✅ got: 1
[🧪 test] reads &optional and &rest in Emacs Lisp
[⚙️ assert] the findings are where they should be
✅ got: ()
[⚙️ assert] the number of findings is right
✅ got: 1
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] optional, keyword and rest parameters are not required
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] counts a definition whose value is a lambda
[⚙️ assert] the number of findings is right
✅ got: 1
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] an optional parameter with a default is still one argument
[⚙️ assert] the findings are where they should be
✅ got: ()
[⚙️ assert] the number of findings is right
✅ got: 1
[🧪 test] accepts a call with every argument
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a keyword to a definition that takes none
[⚙️ assert] the number of findings is right
✅ got: 1
[🧪 test] a named let is a procedure whose parameters are its variables
[⚙️ assert] the findings are where they should be
✅ got: ()
[⚙️ assert] the number of findings is right
✅ got: 1
[🧪 test] a rest parameter takes as many arguments as a caller has
[⚙️ assert] the findings are where they should be
✅ got: ()
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] a key parameter is passed by keyword, not positionally
[⚙️ assert] the findings are where they should be
✅ got: ()
[⚙️ assert] the number of findings is right
✅ got: 1
[🧪 test] reads the parameters of a Common Lisp definition
[⚙️ assert] the number of findings is right
✅ got: 1
[⚙️ assert] the number of findings is right
✅ got: 1
[🧪 test] reads &optional, &rest, &key and &aux in Common Lisp
[⚙️ assert] the findings are where they should be
✅ got: ()
[⚙️ assert] the number of findings is right
✅ got: 1
[⚙️ assert] the findings are where they should be
✅ got: ()
[⚙️ assert] the findings are where they should be
✅ got: ()
[⚙️ assert] the findings are where they should be
✅ got: ()
[⚙️ assert] the number of findings is right
✅ got: 1
[⚙️ assert] the number of findings is right
✅ got: 1
[⚙️ assert] the findings are where they should be
✅ got: ()
[⚙️ assert] the number of findings is right
✅ got: 1
[🧪 test] reads &body of a Common Lisp macro as a rest parameter
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] a call inside a quote is data
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] allow-other-keys takes the keyword set away
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a call with too few arguments
[⚙️ assert] the number of findings is right
✅ got: 1
[🧪 test] an optional parameter raises the ceiling
[⚙️ assert] the findings are where they should be
✅ got: ()
[⚙️ assert] the number of findings is right
✅ got: 1
[🧪 test] reports a keyword with no value
[⚙️ assert] the number of findings is right
✅ got: 1
[🧪 test] a binding of the same name is not the definition
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] a case-lambda is right when some clause accepts the call
[⚙️ assert] the findings are where they should be
✅ got: ()
[⚙️ assert] the number of findings is right
✅ got: 1
[🧪 test] reports a keyword the definition does not take
[⚙️ assert] the number of findings is right
✅ got: 1
[🧪 test] a rest parameter does not lower the floor
[⚙️ assert] the number of findings is right
✅ got: 1
+----------------------------------------------+
[📑 suite] checker: case-literal-datum
[🧪 test] reports a string datum
[⚙️ assert] the findings are where they should be
✅ got: ((1 11))
[🧪 test] reports a string datum written without a list
[⚙️ assert] the findings are where they should be
✅ got: ((1 10))
[🧪 test] accepts symbols and characters
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts a nullary case with a default
[⚙️ assert] the findings are where they should be
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: checkdoc-style-verb
[🧪 test] reports a third-person opening
[⚙️ assert] the findings are where they should be
✅ got: ((2 3))
[🧪 test] accepts the imperative
[⚙️ assert] the findings are where they should be
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: clause-brackets
[🧪 test] reports a cond clause written with parentheses
[⚙️ assert] the findings are where they should be
✅ got: ((1 7) (2 7))
[🧪 test] says nothing when the project preserves what was written
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts a cond clause written with square brackets
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] the default for the other dialects is to preserve
✅ got: preserve
✅ got: preserve
[🧪 test] reports a case clause written with parentheses
[⚙️ assert] the findings are where they should be
✅ got: ((1 9) (2 3))
[🧪 test] the fix rewrites the delimiters
[⚙️ assert] the fix produces the expected text
✅ got: (cond [(= x 1) 'one]
[else 'other])
[🧪 test] the default for Scheme is square
✅ got: square
[🧪 test] follows a project that writes parentheses
[⚙️ assert] the findings are where they should be
✅ got: ((1 7))
[🧪 test] the fixed file has nothing left to report
[⚙️ assert] the fixed text is clean
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: comment-semicolons
[🧪 test] the fixed buffer is clean, so a second run has nothing to do
[⚙️ assert] the fixed text is clean
✅ got: ()
[🧪 test] one pass fixes every comment in the buffer
[⚙️ assert] the fix produces the expected text
✅ got: ;;; first
(define (f x)
;; second
x)
;;; third
[🧪 test] accepts a heading, which has four
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts a margin comment with one semicolon
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts a top-level comment with three semicolons
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] the fix raises a top-level comment to three semicolons
[⚙️ assert] the fix produces the expected text
✅ got: ;;; about the program
(define x 1)
[🧪 test] reports a one-semicolon comment inside a form
[⚙️ assert] the findings are where they should be
✅ got: ((2 3))
[🧪 test] reports a heading inside a form, where two is the level
[⚙️ assert] the findings are where they should be
✅ got: ((2 3))
[🧪 test] reports a top-level comment with two semicolons
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
[🧪 test] accepts a margin comment written without a space
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] the fix leaves the sentence of the comment exactly as it was
[⚙️ assert] the fix produces the expected text
✅ got: ;;; spaced out
(define x 1)
[🧪 test] reports a comment with no space after its semicolons
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
[🧪 test] says nothing about a block comment, which has no semicolons
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] the fix lowers a comment inside a form to two semicolons
[⚙️ assert] the fix produces the expected text
✅ got: (define (f x)
;; a heading in a body
x)
[🧪 test] the fix adds the space after the semicolons and nothing else
[⚙️ assert] the fix produces the expected text
✅ got: ;;; tight
(define x 1)
[🧪 test] the fix leaves a heading at four semicolons
[⚙️ assert] the fix produces the expected text
✅ got: ;;;; Frob Grovel
(define x 1)
[🧪 test] the fix leaves a margin comment alone
[⚙️ assert] the fix produces the expected text
✅ got: (a b) ;Zibblefrotz.
[🧪 test] accepts two semicolons inside a form
[⚙️ assert] the findings are where they should be
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: composition
[🧪 test] does not suggest Guile's compose to Common Lisp
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts a lambda that takes two arguments
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] the fix names the composition
[⚙️ assert] the fix produces the expected text
✅ got: (compose f g)
[🧪 test] the fixed file has nothing left to report
[⚙️ assert] the fixed text is clean
✅ got: ()
[🧪 test] accepts a body that is not a nested call
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts an inner call that takes more than the argument
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a lambda whose body is one call around another
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
+----------------------------------------------+
[📑 suite] checker: dangling-paren
[🧪 test] the fixed file has nothing left to report
[⚙️ assert] the fixed text is clean
✅ got: ()
[🧪 test] reports a closer that starts a line
[⚙️ assert] the findings are where they should be
✅ got: ((3 3))
[🧪 test] the fix pulls the closer onto the previous line
[⚙️ assert] the fix produces the expected text
✅ got: (defun f (x)
x)
[🧪 test] accepts a closer that trails the last element
[⚙️ assert] the findings are where they should be
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: declare-indent
[🧪 test] the fix re-indents the declare
[⚙️ assert] the fix produces the expected text
✅ got: (defun f (x)
(declare (indent 1))
x)
[🧪 test] accepts a declare two columns in
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a declare indented too far
[⚙️ assert] the findings are where they should be
✅ got: ((2 5))
+----------------------------------------------+
[📑 suite] checker: defpackage-use
[🧪 test] accepts a package that only uses :cl
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports each library it finds
[⚙️ assert] the number of findings is right
✅ got: 2
[🧪 test] reports a :use of a library other than :cl
[⚙️ assert] the findings are where they should be
✅ got: ((1 29))
[🧪 test] accepts :import-from
[⚙️ assert] the findings are where they should be
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: defun-no-docstring
[🧪 test] accepts a documented defun
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a defun with no docstring
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
+----------------------------------------------+
[📑 suite] checker: docstring-arguments
[🧪 test] accepts a docstring that names its arguments
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts any spelling of the name
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] looks through optional and rest arguments
[⚙️ assert] the findings are where they should be
✅ got: ((2 3))
[🧪 test] reports each argument the docstring does not mention
[⚙️ assert] the findings are where they should be
✅ got: ((2 3) (2 3))
[🧪 test] says nothing about a defun with no docstring
[⚙️ assert] the findings are where they should be
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: docstring-first-line
[🧪 test] reports a first line that is too long for apropos
[⚙️ assert] the findings are where they should be
✅ got: ((2 3))
[🧪 test] accepts a capitalised sentence with a period
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a first line that starts lowercase
[⚙️ assert] the findings are where they should be
✅ got: ((2 3))
[🧪 test] reports a first line with no full stop
[⚙️ assert] the findings are where they should be
✅ got: ((2 3))
+----------------------------------------------+
[📑 suite] checker: docstring-indent
[🧪 test] reports an indented continuation line
[⚙️ assert] the findings are where they should be
✅ got: ((2 3))
[🧪 test] accepts continuation lines that start at column zero
[⚙️ assert] the findings are where they should be
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: docstring-missing
[🧪 test] a defun with no body is a finding, not a crash
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
[🧪 test] accepts a documented defun
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a defcustom with no docstring
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
[🧪 test] accepts a bare defvar declaration
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a defvar with no docstring
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
[🧪 test] reports a defun with no docstring
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
+----------------------------------------------+
[📑 suite] checker: docstring-texinfo
[🧪 test] reports each undocumented parameter
[⚙️ assert] the findings are where they should be
✅ got: ((2 3))
[🧪 test] says nothing about a definition with no docstring
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] says nothing about a procedure with no parameters
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts a docstring that documents every parameter
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a parameter the docstring does not document
[⚙️ assert] the findings are where they should be
✅ got: ((2 3))
+----------------------------------------------+
[📑 suite] checker: double-colon
[🧪 test] accepts a single-colon reference
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a double-colon reference
[⚙️ assert] the findings are where they should be
✅ got: ((1 2))
[🧪 test] accepts an ordinary symbol
[⚙️ assert] the findings are where they should be
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: ecase-otherwise
[🧪 test] accepts an ecase that covers its cases
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports an otherwise clause in etypecase
[⚙️ assert] the findings are where they should be
✅ got: ((1 26))
[🧪 test] reports a t clause in ecase
[⚙️ assert] the findings are where they should be
✅ got: ((1 16))
[🧪 test] accepts a default clause in case, which is what case is for
[⚙️ assert] the findings are where they should be
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: empty-body
[🧪 test] covers when and unless in Emacs Lisp
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
[🧪 test] reports a cond clause with no body
[⚙️ assert] the findings are where they should be
✅ got: ((1 7))
[🧪 test] accepts a form with a body
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a lambda with no body
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
[🧪 test] reports a cond with no clauses
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
[🧪 test] a case datum is data, not a form
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a let with no body
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
+----------------------------------------------+
[📑 suite] checker: empty-form
[🧪 test] reports the empty list in an argument position
[⚙️ assert] the findings are where they should be
✅ got: ((1 7))
[🧪 test] accepts an empty binding list
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts an empty parameter list
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts the literals list of a syntax-rules transformer
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts the literals list of a syntax-case transformer
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts a quoted empty list
[⚙️ assert] the findings are where they should be
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: eq-nil
[🧪 test] the fix asks null?
[⚙️ assert] the fix produces the expected text
✅ got: (null? x)
[🧪 test] the fixed file has nothing left to report
[⚙️ assert] the fixed text is clean
✅ got: ()
[🧪 test] an Emacs Lisp eq against nil asks null
[⚙️ assert] the fix produces the expected text
✅ got: (null x)
[🧪 test] a Common Lisp eq against nil asks null
[⚙️ assert] the fix produces the expected text
✅ got: (null y)
[🧪 test] accepts a comparison with #f
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports an eq? against the empty list
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
[🧪 test] accepts a comparison with another symbol
[⚙️ assert] the findings are where they should be
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: eq-non-symbol
[🧪 test] the fix writes `eqv?`
[⚙️ assert] the fix produces the expected text
✅ got: (eqv? x 1)
[⚙️ assert] the fixed text is clean
✅ got: ()
[🧪 test] a string asks for `equal?`
[⚙️ assert] the fix produces the expected text
✅ got: (equal? x "a")
[🧪 test] accepts two variables
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] Common Lisp asks for `eql`
[⚙️ assert] the fix produces the expected text
✅ got: (eql x 1.0)
[🧪 test] `memq` of a string asks for `member`
[⚙️ assert] the fix produces the expected text
✅ got: (member "a" xs)
[🧪 test] accepts a symbol, which identity does decide
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports `eq?` against a number
[⚙️ assert] the findings are where they should be
✅ got: ((1 2))
+----------------------------------------------+
[📑 suite] checker: eta-reduction
[🧪 test] accepts a rest argument
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] the fix names the procedure itself
[⚙️ assert] the fix produces the expected text
✅ got: f
[🧪 test] an Emacs Lisp lambda is not a Scheme function designator
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts a body that is more than the call
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts a lambda with two formals
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts a call that passes more than the argument
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] the fixed file has nothing left to report
[⚙️ assert] the fixed text is clean
✅ got: ()
[🧪 test] never rewrites a special form into a value
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts a call that passes something else
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a lambda that only passes its argument on
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
+----------------------------------------------+
[📑 suite] checker: gexp-output-script
[🧪 test] accepts another ungexp in a file-making gexp
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports `#$output` in a `gexp->script`
[⚙️ assert] the findings are where they should be
✅ got: ((1 30))
[🧪 test] accepts `#$output` in a derivation
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports `#$output` in a `program-file`
[⚙️ assert] the findings are where they should be
✅ got: ((1 33))
+----------------------------------------------+
[📑 suite] checker: gexp-quoted
[🧪 test] accepts the long-hand `gexp`
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a gexp written under a quote
[⚙️ assert] the findings are where they should be
✅ got: ((1 12))
[🧪 test] accepts a gexp where it is used
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a gexp under a quasiquote
[⚙️ assert] the findings are where they should be
✅ got: ((1 8))
+----------------------------------------------+
[📑 suite] checker: if-without-else
[🧪 test] the fix rewrites it as when
[⚙️ assert] the fix produces the expected text
✅ got: (when a b)
[🧪 test] the fixed file has nothing left to report
[⚙️ assert] the fixed text is clean
✅ got: ()
[🧪 test] a vector literal is data, not a form
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts an if with an else branch
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] what an unquote puts back is code again
[⚙️ assert] the findings are where they should be
✅ got: ((1 17))
[⚙️ assert] the findings are where they should be
✅ got: ((1 22))
[⚙️ assert] the findings are where they should be
✅ got: ((1 18))
[🧪 test] a quasiquoted or quasisyntaxed template is data
[⚙️ assert] the findings are where they should be
✅ got: ()
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports an if with two arguments
[⚙️ assert] the findings are where they should be
✅ got: ((1 2))
+----------------------------------------------+
[📑 suite] checker: inputs-label-alist
[🧪 test] reports a labelled input list
[⚙️ assert] the findings are where they should be
✅ got: ((1 10))
[🧪 test] accepts a list of packages
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] the fix writes the list of packages
[⚙️ assert] the fix produces the expected text
✅ got: (package (inputs (list gawk)))
[⚙️ assert] the fixed text is clean
✅ got: ()
[🧪 test] leaves an alist outside a package alone
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports the other two input lists as well
[⚙️ assert] the findings are where they should be
✅ got: ((1 10))
[⚙️ assert] the findings are where they should be
✅ got: ((1 10))
+----------------------------------------------+
[📑 suite] checker: interactive-without-arguments
[🧪 test] accepts a spec that supplies the argument
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts a command with no parameters
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a command with a required argument and an empty spec
[⚙️ assert] the findings are where they should be
✅ got: ((3 3))
[🧪 test] accepts optional parameters, which may be left out
[⚙️ assert] the findings are where they should be
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: interactive-without-docstring
[🧪 test] accepts a documented command
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports an interactive command with no docstring
[⚙️ assert] the findings are where they should be
✅ got: ((2 3))
+----------------------------------------------+
[📑 suite] checker: internal-define
[🧪 test] accepts a definition under a let
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts top-level definitions
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts definitions at the head of a body
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a define inside a lambda, after an expression
[⚙️ assert] the findings are where they should be
✅ got: ((3 3))
[🧪 test] reports a define that comes after the first expression
[⚙️ assert] the findings are where they should be
✅ got: ((3 3))
+----------------------------------------------+
[📑 suite] checker: keyword-arguments
[🧪 test] the fields of a record macro are still linted
[⚙️ assert] the findings are where they should be
✅ got: ((4 12))
[🧪 test] reports a call with too many positional arguments
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
[🧪 test] require and provide are declarations
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] the export list of a define-module is data
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] the limit is configuration
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
[🧪 test] accepts the calls that are meant to be variadic
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts a special form
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] a Common Lisp package definition is a declaration
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] a use-modules form is a declaration, not a call
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] a parameter list is not a call
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] a project names its own record macros
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] an operating-system is a record too
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] a Guix package is a record, not a call with too many arguments
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts a call with a readable number of arguments
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts arguments that are already keywords
[⚙️ assert] the findings are where they should be
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: let-sibling
[🧪 test] accepts a name that only appears under a quote
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts independent initializers
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] the fix says let*
[⚙️ assert] the fix produces the expected text
✅ got: (let* ((a (f)) (b (g a))) b)
[🧪 test] the fixed file has nothing left to report
[⚙️ assert] the fixed text is clean
✅ got: ()
[🧪 test] reports an initializer that reaches for a sibling
[⚙️ assert] the findings are where they should be
✅ got: ((1 18))
[🧪 test] reports a reference from a lambda body
[⚙️ assert] the findings are where they should be
✅ got: ((1 18))
[🧪 test] accepts a mention an inner scope binds again
[⚙️ assert] the findings are where they should be
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: let-simplification
[🧪 test] accepts a binding that is used in the body
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] the fix says let
[⚙️ assert] the fix produces the expected text
✅ got: (let ((x (f))) (g x))
[🧪 test] reports a let with no bindings
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
[🧪 test] the fixed files have nothing left to report
[⚙️ assert] "(let ((x (f))) x)\n" is clean after its fix
✅ got: ()
[⚙️ assert] "(let () (f))\n" is clean after its fix
✅ got: ()
[⚙️ assert] "(let* ((x (f))) (g x))\n" is clean after its fix
✅ got: ()
[🧪 test] accepts a let* with two bindings
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts a let with two bindings
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] the fix is the value
[⚙️ assert] the fix produces the expected text
✅ got: (f)
[🧪 test] reports a binding that exists to be returned
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
[🧪 test] the fix is the body
[⚙️ assert] the fix produces the expected text
✅ got: (f)
[🧪 test] reports a let* that binds once
[⚙️ assert] the findings are where they should be
✅ got: ((1 2))
[🧪 test] an Emacs Lisp let is the same let
[⚙️ assert] the fix produces the expected text
✅ got: (f)
[🧪 test] accepts a let with a named let
[⚙️ assert] the findings are where they should be
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: letrec-init-reference
[🧪 test] accepts initializers that mention nothing the form binds
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts mutually recursive procedures
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts a self-reference inside a lambda
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports an initializer that refers to a binding
[⚙️ assert] the findings are where they should be
✅ got: ((1 19))
+----------------------------------------------+
[📑 suite] checker: letrec-single-binding
[🧪 test] accepts a binding that refers to itself
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a letrec with one non-recursive binding
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
[🧪 test] accepts two bindings
[⚙️ assert] the findings are where they should be
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: lexical-binding-missing
[🧪 test] the fix inserts the header
[⚙️ assert] the fix produces the expected text
✅ got: ;;; -*- lexical-binding: t; -*-
;;; f.el --- a package
[🧪 test] accepts a header on the first line
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] the fixed file has nothing left to report
[⚙️ assert] the fixed text is clean
✅ got: ()
[🧪 test] reports a file with no header
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
[🧪 test] accepts a header on the second line
[⚙️ assert] the findings are where they should be
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: library-not-found
[🧪 test] a library imported where nothing it exports is used is reported
✅ got: ((1 23))
[🧪 test] a standard library is never reported missing
✅ got: ()
[🧪 test] a library the project declares is found
✅ got: ()
[🧪 test] a project that declares no library is not judged
✅ got: ()
[🧪 test] an import of a library no file declares is reported
✅ got: ((1 23))
[🧪 test] a library the file declares itself is found
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: line-length
[🧪 test] reports a line over the Scheme limit
[⚙️ assert] the findings are where they should be
✅ got: ((1 97))
[🧪 test] reports a line over the Emacs Lisp limit, which is 80
[⚙️ assert] the findings are where they should be
✅ got: ((1 81))
[🧪 test] the limit can be configured
[⚙️ assert] the findings are where they should be
✅ got: ((1 6))
[🧪 test] accepts a short line
[⚙️ assert] the findings are where they should be
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: loop-keyword-style
[🧪 test] reports symbolic keywords when the style asks for literal ones
[⚙️ assert] the findings are where they should be
✅ got: ((1 7) (1 13) (1 19))
[🧪 test] says nothing when both spellings are accepted
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] the fix rewrites the keywords
[⚙️ assert] the fix produces the expected text
✅ got: (loop :for x :in xs :do (print x))
+----------------------------------------------+
[📑 suite] checker: mixed-lambda-list
[🧪 test] reports a defun that takes both
[⚙️ assert] the findings are where they should be
✅ got: ((1 10))
[🧪 test] accepts optionals alone
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts keywords alone
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a lambda that takes both
[⚙️ assert] the findings are where they should be
✅ got: ((1 9))
[🧪 test] accepts a plain lambda list
[⚙️ assert] the findings are where they should be
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: naming-convention
[🧪 test] accepts the usual hyphenated name
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports an Emacs Lisp defun
[⚙️ assert] the findings are where they should be
✅ got: ((1 8))
[🧪 test] reports a capitalised name
[⚙️ assert] the findings are where they should be
✅ got: ((1 10))
[🧪 test] accepts a name that is punctuation
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] says nothing about a symbol that is not a definition
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a Common Lisp defparameter
[⚙️ assert] the findings are where they should be
✅ got: ((1 15))
[🧪 test] reports an underscore in a procedure name
[⚙️ assert] the findings are where they should be
✅ got: ((1 10))
[🧪 test] reports camelCase in a procedure name
[⚙️ assert] the findings are where they should be
✅ got: ((1 10))
[🧪 test] reports a variable definition too
[⚙️ assert] the findings are where they should be
✅ got: ((1 9))
+----------------------------------------------+
[📑 suite] checker: needless-let*
[🧪 test] accepts a let* with one binding, which is another rule's
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] an Emacs Lisp let* is the same let*
[⚙️ assert] the fix produces the expected text
✅ got: (let ((a (f)) (b (g))) (+ a b))
[🧪 test] reports a let* whose bindings are independent
[⚙️ assert] the findings are where they should be
✅ got: ((1 2))
[🧪 test] the fix says let
[⚙️ assert] the fix produces the expected text
✅ got: (let ((a (f)) (b (g))) (+ a b))
[🧪 test] accepts a let* that depends on its own order
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] the fixed file has nothing left to report
[⚙️ assert] the fixed text is clean
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: negated-if
[🧪 test] the fixed file has nothing left to report
[⚙️ assert] the fixed text is clean
✅ got: ()
[🧪 test] accepts an unless
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a when with a negated test
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
[🧪 test] the fix rewrites a when as an unless
[⚙️ assert] the fix produces the expected text
✅ got: (unless x (go))
[🧪 test] reports an if with a negated test and no else branch
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
[🧪 test] accepts an if whose test is not a negation
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] the fix rewrites the if as an unless
[⚙️ assert] the fix produces the expected text
✅ got: (unless (ready?) (wait) (go))
[🧪 test] reports an if with a negated test
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
+----------------------------------------------+
[📑 suite] checker: nesting-depth
[🧪 test] accepts a `let' inside a `cond' inside a `define'
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a chain of conditionals deeper than the limit
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
[🧪 test] counts a `when' inside an `if'
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
[🧪 test] the limit is configuration
[⚙️ assert] the findings are where they should be
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: number-literal-argument
[🧪 test] accepts numbers
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] leaves a variable alone
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a string compared with a number
[⚙️ assert] the number of findings is right
✅ got: 1
[🧪 test] reports a string added to a number
[⚙️ assert] the number of findings is right
✅ got: 1
[🧪 test] does not read `string-append` as arithmetic
[⚙️ assert] the findings are where they should be
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: package-description-literal
[🧪 test] accepts a literal description
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts a package with no description field
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a description built with `string-append`
[⚙️ assert] the findings are where they should be
✅ got: ((1 23))
[🧪 test] reports a description built with `format`
[⚙️ assert] the findings are where they should be
✅ got: ((1 23))
+----------------------------------------------+
[📑 suite] checker: package-prefix
[🧪 test] accepts a prefixed use
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports an exported symbol used without a prefix
[⚙️ assert] the findings are where they should be
✅ got: ((3 2))
[🧪 test] accepts a file with no export list
[⚙️ assert] the findings are where they should be
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: package-synopsis
[🧪 test] accepts a synopsis as the manual asks for it
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a synopsis that starts in lower case
[⚙️ assert] the findings are where they should be
✅ got: ((1 20))
[🧪 test] leaves a `synopsis` outside a package alone
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a synopsis that opens with an article and ends with a period
[⚙️ assert] the findings are where they should be
✅ got: ((1 31) (1 31))
+----------------------------------------------+
[📑 suite] checker: phase-name-quoting
[🧪 test] reports a phase named by a string
[⚙️ assert] the findings are where they should be
✅ got: ((1 42))
[🧪 test] accepts quoted names in `add-before` and `add-after`
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] the fix quotes it
[⚙️ assert] the fix produces the expected text
✅ got: (modify-phases %standard-phases (delete 'configure))
[⚙️ assert] the fixed text is clean
✅ got: ()
[🧪 test] leaves a `replace` outside `modify-phases` alone
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports an unquoted phase name
[⚙️ assert] the findings are where they should be
✅ got: ((1 41))
+----------------------------------------------+
[📑 suite] checker: practices
[🧪 test] a quoted number is reported and the quote is removable
[⚙️ assert] the number of findings is right
✅ got: 1
[⚙️ assert] the fix produces the expected text
✅ got: 5
[⚙️ assert] the fixed text is clean
✅ got: ()
[🧪 test] a cond with clauses after else is reported
[⚙️ assert] the number of findings is right
✅ got: 1
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] six parameters are reported and five are not
[⚙️ assert] the number of findings is right
✅ got: 1
[⚙️ assert] the findings are where they should be
✅ got: ()
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] a case datum listed twice is reported
[⚙️ assert] the number of findings is right
✅ got: 1
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] eq? on a number and on a string are reported
[⚙️ assert] the number of findings is right
✅ got: 1
[⚙️ assert] the number of findings is right
✅ got: 1
[🧪 test] only the required positional parameters are counted
[⚙️ assert] the findings are where they should be
✅ got: ()
[⚙️ assert] the findings are where they should be
✅ got: ()
[⚙️ assert] the findings are where they should be
✅ got: ()
[⚙️ assert] the number of findings is right
✅ got: 0
[🧪 test] a quoted string, character and list are told apart
[⚙️ assert] the number of findings is right
✅ got: 1
[⚙️ assert] the number of findings is right
✅ got: 1
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] a quote around a symbol is left alone
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] eq? on two variables and eqv? on a number are silent
[⚙️ assert] the findings are where they should be
✅ got: ()
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] a defun's parameters are all of them, not all but the first
[⚙️ assert] the number of findings is right
✅ got: 1
[🧪 test] a defcustom without :type is reported in Emacs Lisp
[⚙️ assert] the number of findings is right
✅ got: 1
[⚙️ assert] the findings are where they should be
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: predicate-name
[🧪 test] accepts a procedure that returns something else
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a procedure whose last form is another predicate
[⚙️ assert] the findings are where they should be
✅ got: ((1 10))
[🧪 test] Emacs Lisp accepts the -p suffix
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts a name that ends in a question mark
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] a docstring is not the returned value
[⚙️ assert] the findings are where they should be
✅ got: ((1 10))
[🧪 test] Emacs Lisp reports a name with neither suffix
[⚙️ assert] the findings are where they should be
✅ got: ((1 8))
[🧪 test] reports a procedure that returns a comparison
[⚙️ assert] the findings are where they should be
✅ got: ((1 10))
+----------------------------------------------+
[📑 suite] checker: provide-missing
[🧪 test] accepts a file that provides its feature
[⚙️ assert] the number of findings is right
✅ got: 0
[🧪 test] accepts a file that defines nothing
[⚙️ assert] the number of findings is right
✅ got: 0
[🧪 test] reports a file that defines but never provides
[⚙️ assert] the number of findings is right
✅ got: 1
+----------------------------------------------+
[📑 suite] checker: quasiquote-unquote-constant
[🧪 test] accepts an unquoted variable
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports an unquoted number inside a quasiquote
[⚙️ assert] the findings are where they should be
✅ got: ((1 5))
[🧪 test] reports the long-hand form too
[⚙️ assert] the findings are where they should be
✅ got: ((1 13))
+----------------------------------------------+
[📑 suite] checker: reader-prefix-break
[🧪 test] accepts a quote attached to its datum
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] a function quote is covered too
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
[🧪 test] the fix joins the prefix to the datum
[⚙️ assert] the fix produces the expected text
✅ got: '(a)
[🧪 test] reports a quote separated from its datum
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
+----------------------------------------------+
[📑 suite] checker: redundant-identity
[🧪 test] reports a funcall of a function name
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
[🧪 test] accepts a plain call
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports an identity call
[⚙️ assert] the findings are where they should be
✅ got: ((1 21))
+----------------------------------------------+
[📑 suite] checker: redundant-progn
[🧪 test] the fix splices the body
[⚙️ assert] the fix produces the expected text
✅ got: (define (f) (a) (b))
[🧪 test] the fixed file has nothing left to report
[⚙️ assert] the fixed text is clean
✅ got: ()
[🧪 test] reports a progn that is the only body form
[⚙️ assert] the findings are where they should be
✅ got: ((1 13))
[🧪 test] accepts a progn with company
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports one in a defun
[⚙️ assert] the findings are where they should be
✅ got: ((1 13))
[🧪 test] a vector whose first element is progn is a literal, not a body
[⚙️ assert] the findings are where they should be
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: require-cl
[🧪 test] accepts another library
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a require of cl
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
[🧪 test] reports the pieces of cl as well
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
[🧪 test] accepts cl-lib
[⚙️ assert] the findings are where they should be
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: save-excursion-set-buffer
[🧪 test] accepts with-current-buffer around an excursion
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a set-buffer inside save-excursion
[⚙️ assert] the findings are where they should be
✅ got: ((1 17))
[🧪 test] reports one nested in a body form
[⚙️ assert] the findings are where they should be
✅ got: ((1 25))
[🧪 test] accepts an excursion that changes nothing
[⚙️ assert] the findings are where they should be
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: sha256-base32
[🧪 test] leaves a `sha256` outside an origin alone
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a hash with an upper-case character
[⚙️ assert] the findings are where they should be
✅ got: ((1 17))
[🧪 test] accepts 52 lower-case characters
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a base32 string of the wrong length
[⚙️ assert] the findings are where they should be
✅ got: ((1 17))
[🧪 test] reports a hash that is not written in base32
[⚙️ assert] the findings are where they should be
✅ got: ((1 17))
+----------------------------------------------+
[📑 suite] checker: single-letter-name
[🧪 test] reports the binding of a `let'
[⚙️ assert] the findings are where they should be
✅ got: ((1 8))
[🧪 test] accepts an ignored parameter
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a parameter of a `lambda'
[⚙️ assert] the findings are where they should be
✅ got: ((1 10))
[🧪 test] reports each single-letter parameter of a definition
[⚙️ assert] the findings are where they should be
✅ got: ((1 15) (1 17))
[🧪 test] a setting replaces the default list rather than extending it
[⚙️ assert] the findings are where they should be
✅ got: ((1 10))
[🧪 test] reports a parameter of a Common Lisp defun
[⚙️ assert] the findings are where they should be
✅ got: ((1 11))
[🧪 test] the accepted names are a setting
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] says nothing about a definition that names a program
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts an index variable, which is what the setting is for
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a parameter of an Emacs Lisp defun
[⚙️ assert] the findings are where they should be
✅ got: ((1 11))
[🧪 test] accepts names made of words
[⚙️ assert] the findings are where they should be
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: special-variable-name
[🧪 test] accepts a constant written with plus signs
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports earmuffs in Emacs Lisp
[⚙️ assert] the findings are where they should be
✅ got: ((1 9))
[🧪 test] reports a Common Lisp special variable without earmuffs
[⚙️ assert] the findings are where they should be
✅ got: ((1 15))
[🧪 test] reports a Common Lisp constant without plus signs
[⚙️ assert] the findings are where they should be
✅ got: ((1 14))
[🧪 test] accepts an earmuffed one
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts a plain Emacs Lisp variable
[⚙️ assert] the findings are where they should be
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: string-append-file-append
[🧪 test] the fix writes `file-append`
[⚙️ assert] the fix produces the expected text
✅ got: #~(system* #$(file-append coreutils "/bin/ls"))
[⚙️ assert] the fixed text is clean
✅ got: ()
[🧪 test] reports it in a quasiquoted build body
[⚙️ assert] the number of findings is right
✅ got: 1
[🧪 test] accepts `file-append`
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a run-time `string-append` in a gexp
[⚙️ assert] the findings are where they should be
✅ got: ((1 12))
[🧪 test] accepts the output directory, which is not a package
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] leaves a `string-append` outside a build body alone
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] and leaves that body as it found it
[⚙️ assert] the fix produces the expected text
✅ got: (gexp->derivation "x" `(system* (string-append ,coreutils "/bin/ls")))
+----------------------------------------------+
[📑 suite] checker: string-literal-argument
[🧪 test] accepts strings
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a boolean passed to `string-length`
[⚙️ assert] the number of findings is right
✅ got: 1
[🧪 test] reports a number passed to `string-append`
[⚙️ assert] the number of findings is right
✅ got: 1
[🧪 test] leaves a variable alone, whatever it holds
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] does not read an index as a string
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports the character position a comparison takes
[⚙️ assert] the findings are where they should be
✅ got: ((1 15))
+----------------------------------------------+
[📑 suite] checker: sxml-attributes
[🧪 test] accepts an element whose attributes come first
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a second attribute list
[⚙️ assert] the findings are where they should be
✅ got: ((1 22))
[🧪 test] reports attributes that come after a child
[⚙️ assert] the findings are where they should be
✅ got: ((1 14))
[🧪 test] accepts an element with no attributes at all
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts a document of nested elements
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports an empty attribute list
[⚙️ assert] the findings are where they should be
✅ got: ((1 6))
+----------------------------------------------+
[📑 suite] checker: sxml-child
[🧪 test] accepts elements, strings and numbers as children
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] an element with no attributes is not judged
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a list of elements where elements belong
[⚙️ assert] the findings are where they should be
✅ got: ((1 18))
[🧪 test] accepts the same list without the extra level
[⚙️ assert] the findings are where they should be
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: sxml-empty-element
[🧪 test] leaves a repeated attribute list to the rule that names it
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] the fix keeps the layout the element was written with
[⚙️ assert] the fix produces the expected text
✅ got: (div
(@ (class "card")) "")
[🧪 test] reports the inner element of a document
[⚙️ assert] the findings are where they should be
✅ got: ((1 19))
[🧪 test] accepts an element with a child
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts an element with no attributes at all
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] the fix writes the child that closes the element
[⚙️ assert] the fix produces the expected text
✅ got: (div (@ (class "my-2 px-3")) "")
[🧪 test] accepts the same element with an empty text child
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports every empty element, not only the outermost
[⚙️ assert] the findings are where they should be
✅ got: ((2 6) (3 6))
[🧪 test] reports an element with attributes and nothing else
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
[🧪 test] a comment inside the element does not make it a parent
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
[🧪 test] leaves an empty attribute list to the rule that names it
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] the fixed text is clean
[⚙️ assert] the fixed text is clean
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: tabs
[🧪 test] the fixed file has nothing left to report
[⚙️ assert] the fixed text is clean
✅ got: ()
[🧪 test] reports a tab used for indentation
[⚙️ assert] the findings are where they should be
✅ got: ((2 1))
[🧪 test] a tab inside a string is data, not indentation
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] the fix replaces the tab with spaces
[⚙️ assert] the fix produces the expected text
✅ got: (a
b)
[🧪 test] accepts indentation made of spaces
[⚙️ assert] the findings are where they should be
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: trailing-blank-lines
[🧪 test] reports four blank lines at the end of a file
[⚙️ assert] the number of findings is right
✅ got: 1
[🧪 test] accepts a file with one blank line at the end
[⚙️ assert] the number of findings is right
✅ got: 0
[🧪 test] the fixed file has nothing left to report
[⚙️ assert] the fixed text is clean
✅ got: ()
[🧪 test] the fix trims the end of the file to one blank line
[⚙️ assert] the fix produces the expected text
✅ got: (define x 1)
[🧪 test] accepts a file with a single trailing newline
[⚙️ assert] the number of findings is right
✅ got: 0
+----------------------------------------------+
[📑 suite] checker: trailing-whitespace
[🧪 test] reports every line of a file
[⚙️ assert] the findings are where they should be
✅ got: ((1 2) (2 2))
[🧪 test] reports a line that ends with a space
[⚙️ assert] the findings are where they should be
✅ got: ((1 2))
[🧪 test] reports a line that ends with a tab
[⚙️ assert] the findings are where they should be
✅ got: ((1 2))
[🧪 test] the fixed file has nothing left to report
[⚙️ assert] the fixed text is clean
✅ got: ()
[🧪 test] the fix strips the whitespace
[⚙️ assert] the fix produces the expected text
✅ got: x
y
[🧪 test] accepts a file whose lines are clean
[⚙️ assert] the findings are where they should be
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: ungexp-outside-gexp
[🧪 test] accepts every form inside a gexp
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts the long-hand forms inside `gexp`
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports `#$` with no gexp around it
[⚙️ assert] the findings are where they should be
✅ got: ((1 7))
[🧪 test] reports `#+@` with no gexp around it
[⚙️ assert] the findings are where they should be
✅ got: ((1 7))
[🧪 test] reports a gexp that lost its `#~`
[⚙️ assert] the findings are where they should be
✅ got: ((1 11))
+----------------------------------------------+
[📑 suite] checker: unless-without-body
[🧪 test] reports one in Common Lisp too
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
[🧪 test] accepts an unless with a body
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports an unless with no body
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
+----------------------------------------------+
[📑 suite] checker: unmatched-parens
[🧪 test] accepts a balanced file
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports an unmatched opening parenthesis at the opener
[⚙️ assert] the findings are where they should be
✅ got: ((1 1) (1 4))
[🧪 test] reports a stray closing parenthesis
[⚙️ assert] the findings are where they should be
✅ got: ((1 2))
+----------------------------------------------+
[📑 suite] checker: unused-argument
[🧪 test] accepts a parameter that is used
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reads a parameter with a default
[⚙️ assert] the findings are where they should be
✅ got: ((1 25))
[🧪 test] reads the parameters of a defun
[⚙️ assert] the findings are where they should be
✅ got: ((1 13))
[🧪 test] accepts a lambda that uses its parameter
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reads a specialized Common Lisp parameter
[⚙️ assert] the findings are where they should be
✅ got: ((1 19))
[🧪 test] reports a parameter the body never uses
[⚙️ assert] the findings are where they should be
✅ got: ((1 14))
[🧪 test] accepts a parameter named with an underscore
[⚙️ assert] the findings are where they should be
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: unused-definition
[🧪 test] a file with no define-module is not judged
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] a module with no #:export clause is not judged
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] an exported definition is the module's surface
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] a name mentioned under a quote counts as mentioned
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] a module that says it exports nothing is judged
[⚙️ assert] the findings are where they should be
✅ got: ((3 10))
[🧪 test] a definition another one uses is not dead
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] the name in the export list is the name that counts
[⚙️ assert] the findings are where they should be
✅ got: ((3 10))
[🧪 test] reports a definition nothing uses and the module does not export
[⚙️ assert] the findings are where they should be
✅ got: ((4 10))
+----------------------------------------------+
[📑 suite] checker: unused-import-from
[🧪 test] reports an imported name the file never uses
[⚙️ assert] the number of findings is right
✅ got: 1
[🧪 test] accepts an imported name the file uses
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] a package with no import clause is fine
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reads every name of the clause
[⚙️ assert] the number of findings is right
✅ got: 1
+----------------------------------------------+
[📑 suite] checker: unused-import
[🧪 test] reports a renamed import nothing uses, by its new name
[⚙️ assert] the fix produces the expected text
✅ got: (import (rename (srfi 1) (fold foldl)))
(display (foldl + 0 (list 1)))
[🧪 test] a name used inside a template that spells unquote counts as used
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] one unused spec of two is deleted, and the form stays
[⚙️ assert] the fix produces the expected text
✅ got: (import (scheme base))
(display 1)
[🧪 test] a plain import of a library sift cannot read is left alone
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] the fix removes the whole import when it is the only thing on its line
[⚙️ assert] the fix produces the expected text
✅ got: (display 1)
[🧪 test] reports the name of an `only` clause nothing uses
[⚙️ assert] the findings are where they should be
✅ got: ((1 29))
[🧪 test] a name used inside a quasiquote counts as used
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] a name used only inside a quote does not count as used
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
[🧪 test] a `#:use-module` clause nothing uses is reported, keyword and all
[⚙️ assert] one finding, on the clause
✅ got: 1
[⚙️ assert] the fix removes the clause and the line it was on
✅ got: (define-module (proj client)
#:export (f))
(define (f x) x)
[🧪 test] an import used inside a library body is read
[⚙️ assert] the findings are where they should be
✅ got: ((3 25))
[🧪 test] every name in an `only` clause used is silent
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] an `only` clause with nothing used is one finding, on the form
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
[🧪 test] the fix deletes the name and the space before it
[⚙️ assert] the fix produces the expected text
✅ got: (import (only (srfi 1) fold))
(display (fold + 0 (list 1 2)))
[🧪 test] a `#:use-module` clause whose names are used is silent
[⚙️ assert] the name the clause brings in is used
✅ got: 0
+----------------------------------------------+
[📑 suite] checker: use-modules-in-gexp
[🧪 test] accepts a body the builder was given the modules for
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a build module imported inside a bare gexp
[⚙️ assert] the findings are where they should be
✅ got: ((1 3))
[🧪 test] leaves a library of the host stratum alone
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports it in a quasiquoted build body
[⚙️ assert] the number of findings is right
✅ got: 1
[🧪 test] accepts the extension modules too
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] accepts a gexp marked with `with-imported-modules`
[⚙️ assert] the findings are where they should be
✅ got: ()
+----------------------------------------------+
[📑 suite] checker: when-without-body
[🧪 test] accepts a when with a body
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a when with no body in Common Lisp
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
[🧪 test] reports a when with no body
[⚙️ assert] the findings are where they should be
✅ got: ((1 1))
+----------------------------------------------+
[📑 suite] checker: wrap-in-let
[🧪 test] the depth limit is configuration
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] reports a body form with too many elements
[⚙️ assert] the findings are where they should be
✅ got: ((2 3))
[🧪 test] reports a body form that nests too deeply
[⚙️ assert] the findings are where they should be
✅ got: ((2 3))
[🧪 test] accepts a body form that is already split up
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] the element limit is configuration
[⚙️ assert] the findings are where they should be
✅ got: ()
[🧪 test] there is no automatic fix
✅ got: #f
+----------------------------------------------+
[📑 suite] cli
[🧪 test] --stdin with one file is the label, and is not a usage error
[⚙️ assert] the exit status is right
✅ got: 0
[🧪 test] fix is lint --fix
[⚙️ assert] the exit status is right
✅ got: 0
[⚙️ assert] the text matches
✅ got: (when (ready?) (go))
[🧪 test] format --write rewrites the file in place
[⚙️ assert] the exit status is right
✅ got: 0
[⚙️ assert] the text matches
✅ got: (define (f x)
(+ x 1))
[🧪 test] fix --force fixes what it can read
[⚙️ assert] the exit status is right
✅ got: 1
[⚙️ assert] the trailing whitespace is gone
✅ got: (define (f x)
[🧪 test] lint reports findings with status 1
[⚙️ assert] the exit status is right
✅ got: 1
✅ got: [trailing-whitespace]
[🧪 test] lint --fix rewrites the file and reports what is left
[⚙️ assert] the exit status is right
✅ got: 0
[⚙️ assert] the text matches
✅ got: (when (ready?) (go))
[🧪 test] an unknown command is a usage error, with status 2
[⚙️ assert] the exit status is right
✅ got: 2
✅ got: Usage:
[🧪 test] config explain documents a key
[⚙️ assert] the exit status is right
✅ got: 0
✅ got: --line-length
[🧪 test] doctor says what ran and what it decided
[⚙️ assert] the exit status is right
✅ got: 0
[⚙️ assert] doctor starts with the version
✅ got: sift
✅ got: rules
✅ got: sift.yaml
[🧪 test] a parse error is a refusal, with status 2
[⚙️ assert] the exit status is right
✅ got: 2
✅ got: parse error
[🧪 test] explain answers 2 for a checker it does not know
[⚙️ assert] the exit status is right
✅ got: 2
✅ got: unknown checker
[🧪 test] format writes the formatted source to stdout
[⚙️ assert] the exit status is right
✅ got: 0
[⚙️ assert] the text matches
✅ got: (define (square x)
(* x x))
(define (classify n)
(cond [(< n 0) 'negative]
[(= n 0) 'zero]
[else 'positive]))
(let ((a 1)
(b 2))
(+ a b (* a b)))
[🧪 test] doctor names the library without a `..' in it
[⚙️ assert] the exit status is right
✅ got: 0
[⚙️ assert] the library line is a directory under the checkout
✅ got: /src
✅ got: ..
[🧪 test] lint --format=json emits one array for the run
[⚙️ assert] the exit status is right
✅ got: 1
[⚙️ assert] it starts with an array
✅ got: #t
✅ got: "severity"
✅ got: "checker"
✅ got: "line"
[🧪 test] version prints the version and succeeds
[⚙️ assert] the exit status is right
✅ got: 0
✅ got: sift
[🧪 test] a document format answers a run of several files once
[⚙️ assert] the exit status is right
✅ got: 1
[⚙️ assert] it is one array
✅ got: #t
[⚙️ assert] one array holds them all
✅ got: 1
[🧪 test] lint --format=sarif describes the rules, the artifacts and the run
[⚙️ assert] the exit status is right
✅ got: 1
[⚙️ assert] the document carries "fullDescription":
✅ got: "fullDescription":
[⚙️ assert] the document carries "help":{"text":
✅ got: "help":{"text":
[⚙️ assert] the document carries "helpUri":
✅ got: "helpUri":
[⚙️ assert] the document carries "shortDescription":
✅ got: "shortDescription":
[⚙️ assert] the document carries "invocations":[{"executionSuccessful":true}]
✅ got: "invocations":[{"executionSuccessful":true}]
[⚙️ assert] the document carries "artifacts":[{"location":{"uri":"tests/fixtures/lint/dirty.scm"}
✅ got: "artifacts":[{"location":{"uri":"tests/fixtures/lint/dirty.scm"}
[⚙️ assert] the document carries "roles":["analysisTarget"]
✅ got: "roles":["analysisTarget"]
[⚙️ assert] the document carries "index":0
✅ got: "index":0
[⚙️ assert] the document carries "columnKind":"unicodeCodePoints"
✅ got: "columnKind":"unicodeCodePoints"
[⚙️ assert] the document carries "partialFingerprints":{"siftFingerprint/v1":
✅ got: "partialFingerprints":{"siftFingerprint/v1":
[⚙️ assert] the document carries "charOffset":
✅ got: "charOffset":
[⚙️ assert] the document carries "charLength":
✅ got: "charLength":
[⚙️ assert] the document carries "ruleIndex":0
✅ got: "ruleIndex":0
[⚙️ assert] the rule is named by its code
✅ got: "ruleId":"SIFT001"
[🧪 test] --brackets=parens overrides the Scheme default
[⚙️ assert] the exit status is right
✅ got: 0
✅ got: (cond ((< n 0) 1)
[🧪 test] ci refuses to fix
[⚙️ assert] the exit status is right
✅ got: 2
✅ got: never fixes
[🧪 test] lint --format=json carries the rule code
✅ got: "code"
✅ got: SIFT001
[🧪 test] lint --format=github writes workflow commands
[⚙️ assert] the exit status is right
✅ got: 1
✅ got: ::warning file=
✅ got: title=SIFT001 [trailing-whitespace]
[🧪 test] an unknown checker is a usage error
[⚙️ assert] the exit status is right
✅ got: 2
✅ got: unknown checker
[🧪 test] an unreadable file is a usage error
[⚙️ assert] the exit status is right
✅ got: 2
✅ got: cannot read
[🧪 test] lint --checker runs only the checker it names
[⚙️ assert] the exit status is right
✅ got: 0
✅ got: trailing-whitespace
[🧪 test] lint --fix --stdin prints the fixed source to stdout
[⚙️ assert] the exit status is right
✅ got: 0
[⚙️ assert] the text matches
✅ got: (when (ready?) (go))
[🧪 test] every option that takes a value accepts both spellings
[⚙️ assert] --dialect value is accepted
✅ got: 0
[⚙️ assert] --dialect spells the same both ways
✅ got: (define (f x)
(+ x 1))
[⚙️ assert] --severity value is accepted
✅ got: 0
[⚙️ assert] --severity spells the same both ways
✅ got: (define (f x)
(+ x 1))
[⚙️ assert] --format value is accepted
✅ got: 0
[⚙️ assert] --format spells the same both ways
✅ got: (define (f x)
(+ x 1))
[⚙️ assert] --style value is accepted
✅ got: 0
[⚙️ assert] --style spells the same both ways
✅ got: (define (f x)
(+ x 1))
[⚙️ assert] --line-length value is accepted
✅ got: 0
[⚙️ assert] --line-length spells the same both ways
✅ got: (define (f x)
(+ x 1))
[⚙️ assert] --indent value is accepted
✅ got: 0
[⚙️ assert] --indent spells the same both ways
✅ got: (define (f x)
(+ x 1))
[⚙️ assert] --brackets value is accepted
✅ got: 0
[⚙️ assert] --brackets spells the same both ways
✅ got: (define (f x)
(+ x 1))
[⚙️ assert] --label value is accepted
✅ got: 0
[⚙️ assert] --label spells the same both ways
✅ got: (define (f x)
(+ x 1))
[🧪 test] lint --quiet keeps the findings and drops the summary
[⚙️ assert] the exit status is right
✅ got: 1
✅ got: [trailing-whitespace]
✅ got: file checked
[🧪 test] an unreadable file says why, in words
[⚙️ assert] the exit status is right
✅ got: 2
✅ got: no-such-file.scm
✅ got: ~A
[🧪 test] lint --format=sarif writes a SARIF document
[⚙️ assert] the exit status is right
✅ got: 1
✅ got: "version":"2.1.0"
✅ got: "rules":
✅ got: "ruleId":"SIFT001"
✅ got: "artifactLocation"
[🧪 test] check on an already formatted file succeeds
[⚙️ assert] the exit status is right
✅ got: 0
[⚙️ assert] the text matches
✅ got:
[🧪 test] fix refuses a file that does not parse, and says why
[⚙️ assert] the exit status is right
✅ got: 2
✅ got: parse error
[⚙️ assert] the file is left exactly as it was
✅ got: (define (f x)
(a b
[🧪 test] an unknown bracket style is a usage error
[⚙️ assert] the exit status is right
✅ got: 2
✅ got: unknown bracket style
[🧪 test] --stdin with more than one file is a usage error
[⚙️ assert] the exit status is right
✅ got: 2
✅ got: at most one file
[🧪 test] a document format writes one document for the whole run
[⚙️ assert] the exit status is right
✅ got: 1
[⚙️ assert] there is one document
✅ got: 1
[⚙️ assert] both files are artifacts
✅ got: 2
✅ got: "ruleId":"format"
✅ got: "ruleId":"SIFT001"
[🧪 test] format --diff prints a patch and exits 1
[⚙️ assert] the exit status is right
✅ got: 1
✅ got: @@
✅ got: -
[🧪 test] a directory operand skips entries it cannot ask about
[⚙️ assert] the exit status is right
✅ got: 1
[⚙️ assert] the file that could be read was read
✅ got: real.scm
[🧪 test] explain leads with the rule's code
✅ got: SIFT012
[🧪 test] ci does not write the file it is judging
[⚙️ assert] the exit status is right
✅ got: 1
[⚙️ assert] the text matches
✅ got: (define (f x)
(+ x 1))
[🧪 test] ci fails when the linter has something to say
[⚙️ assert] the exit status is right
✅ got: 1
✅ got: [trailing-whitespace]
[🧪 test] ci fails when a file is not formatted
[⚙️ assert] the exit status is right
✅ got: 1
✅ got: @@
[🧪 test] --force formats what can be read
[⚙️ assert] the exit status is right
✅ got: 0
[🧪 test] --label names the source in diagnostics
[⚙️ assert] the exit status is right
✅ got: 1
✅ got: my-buffer.scm
[🧪 test] --stdin and --stdout work as a filter
[⚙️ assert] the exit status is right
✅ got: 0
[⚙️ assert] the text matches
✅ got: (define (f x)
(+ x 1))
[🧪 test] list-checkers prints a table
[⚙️ assert] the exit status is right
✅ got: 0
✅ got: trailing-whitespace
✅ got: SEVERITY
[🧪 test] ci passes on a clean file
[⚙️ assert] the exit status is right
✅ got: 0
[🧪 test] an unknown dialect is a usage error
[⚙️ assert] the exit status is right
✅ got: 2
✅ got: unknown dialect
[🧪 test] --version prints the version without a subcommand
[⚙️ assert] the exit status is right
✅ got: 0
✅ got: sift
[🧪 test] install-hooks writes a pre-commit hook
[⚙️ assert] the exit status is right
✅ got: 0
[⚙️ assert] the hook was written
✅ got: #t
✅ got: sift
[🧪 test] check reports a difference with status 1
[⚙️ assert] the exit status is right
✅ got: 1
✅ got: @@
[🧪 test] format --diff on a formatted file prints nothing and exits 0
[⚙️ assert] the exit status is right
✅ got: 0
[⚙️ assert] the text matches
✅ got:
[🧪 test] lint on a clean file succeeds and prints a summary
[⚙️ assert] the exit status is right
✅ got: 0
✅ got: 1 file checked
[🧪 test] install-hooks leaves an existing hook alone
[⚙️ assert] the exit status is right
✅ got: 2
✅ got: already exists
[🧪 test] install-hooks --force replaces one
[⚙️ assert] the exit status is right
✅ got: 0
✅ got: sift
[🧪 test] config show prints the effective configuration
[⚙️ assert] the exit status is right
✅ got: 0
✅ got: line-length
✅ got: style
[🧪 test] install-hooks outside a repository is a usage error
[⚙️ assert] the exit status is right
✅ got: 2
✅ got: no git repository
[🧪 test] --write with --stdout is a usage error
[⚙️ assert] the exit status is right
✅ got: 2
✅ got: cannot be used together
[🧪 test] ci --format=github turns formatting differences into annotations
[⚙️ assert] the exit status is right
✅ got: 1
✅ got: ::error file=
[🧪 test] list-checkers prints each rule's code
✅ got: SIFT001
✅ got: CODE
[🧪 test] lint --format=null says nothing at all
[⚙️ assert] the exit status is right
✅ got: 1
[⚙️ assert] the text matches
✅ got:
[🧪 test] fix --stdin refuses a buffer that does not parse
[⚙️ assert] the exit status is right
✅ got: 2
[⚙️ assert] no text is written to standard output
✅ got:
[🧪 test] lint --exclude-checker skips the checker it names
✅ got: trailing-whitespace
[🧪 test] explain documents a checker
[⚙️ assert] the exit status is right
✅ got: 0
✅ got: DESCRIPTION
✅ got: DIALECTS
[🧪 test] list-checkers --dialect filters to the dialect
[⚙️ assert] the exit status is right
✅ got: 0
✅ got: docstring-missing
✅ got: internal-define
+----------------------------------------------+
[📑 suite] project configuration
[🧪 test] an empty flow sequence is an empty list of names
[⚙️ assert] the exit status is right
✅ got: 0
✅ got: exclude-checkers: []
[🧪 test] the inlay hints a project asks for are readable in YAML
[⚙️ assert] the exit status is right
✅ got: 0
✅ got: inlay-hints: [parameters, types]
[🧪 test] and off is a shape the setting accepts
[⚙️ assert] the exit status is right
✅ got: 0
✅ got: inlay-hints: []
[🧪 test] indent-rules written as a YAML sequence indents the macro
[⚙️ assert] the exit status is right
✅ got: 0
[⚙️ assert] the text matches
✅ got: (with-my-thing
(a)
(b))
+----------------------------------------------+
[📑 suite] declarations: a declaration is not a call
[🧪 test] a parameter list is not a call, however long it is
[⚙️ assert] elisp parameter list: (defun demo-f (a b c d e f g)
✅ got: ()
[⚙️ assert] elisp parameter list: (lambda (a b c d e f g) (list a b c d e f g))
✅ got: ()
[⚙️ assert] scheme parameter list: (define (demo-f a b c d e f g)
✅ got: ()
[⚙️ assert] scheme parameter list: (define* (demo-g a b #:key c d e f g h)
✅ got: ()
[⚙️ assert] cl parameter list: (defmethod area ((shape circle) &key (scale 1) &allow-other-keys)
✅ got: ()
[🧪 test] a parameter list of keywords and optionals is not a call
✅ got: ()
[🧪 test] a call with too many positional arguments is still reported
✅ got: 1
[🧪 test] a parameter list with too many required parameters is still reported
✅ got: 1
[🧪 test] a definition's body is still read as code
✅ got: 1
[🧪 test] no rule about calls reports a declaration
[⚙️ assert] scheme declaration: (define-module (demo thing)
✅ got: ()
[⚙️ assert] scheme declaration: (use-modules (srfi srfi-1)
✅ got: ()
[⚙️ assert] scheme declaration: (import (scheme base)
✅ got: ()
[⚙️ assert] scheme declaration: (export one
✅ got: ()
[⚙️ assert] scheme declaration: (define-library (demo lib)
✅ got: ()
[⚙️ assert] scheme declaration: (library (demo r6rs)
✅ got: ()
[⚙️ assert] scheme declaration: (declare (pure? #t) (blocked #:all) (names one two three four five six))
✅ got: ()
[⚙️ assert] elisp declaration: (require 'cl-lib)
✅ got: ()
[⚙️ assert] elisp declaration: (use-package flymake
✅ got: ()
[⚙️ assert] elisp declaration: (declare-function sift-mode "sift" (&optional arg))
✅ got: ()
[⚙️ assert] elisp declaration: (eval-when-compile (require 'cl-lib))
✅ got: ()
[⚙️ assert] elisp declaration: (setq one 1 two 2 three 3 four 4 five 5 six 6)
✅ got: ()
[⚙️ assert] cl declaration: (defpackage :demo
✅ got: ()
[⚙️ assert] cl declaration: (in-package :demo)
✅ got: ()
[⚙️ assert] cl declaration: (declaim (optimize (speed 3) (safety 0) (debug 0) (space 0) (compilation-speed 0)))
✅ got: ()
[⚙️ assert] cl declaration: (proclaim '(ftype (function (fixnum fixnum) fixnum) add))
✅ got: ()
[⚙️ assert] cl declaration: (defmethod area ((shape circle) &key (scale 1) &allow-other-keys)
✅ got: ()
[⚙️ assert] cl declaration: (defun add (a b &optional (c 1) &key (d 2) &allow-other-keys)
✅ got: ()
+----------------------------------------------+
[📑 suite] definitions: scope and bindings
[🧪 test] the name of a definition is a definition of itself
✅ got: (f 1 10)
[🧪 test] a binding inside a template still wins over the pattern
✅ got: (tmp 4 13)
[🧪 test] a parameter is nearer than the definition of the same name
✅ got: (x 1 12)
[🧪 test] a define-syntax is a macro in the outline
✅ got: ((swap! macro))
[🧪 test] an underscore binds nothing
✅ got: #f
[🧪 test] an internal definition is a definition of the body it sits in
✅ got: (g 2 12)
[🧪 test] letrec-syntax binds its keyword over the body too
✅ got: (with-two 1 18)
[🧪 test] a pattern variable inside a nested list is still a variable
✅ got: (a 3 10)
[🧪 test] a named let binds its own name over the body
✅ got: (loop 2 8)
[🧪 test] a template variable is defined by its pattern
✅ got: (a 3 9)
[🧪 test] a renamed ellipsis binds nothing either
✅ got: #f
[🧪 test] let-syntax binds its keyword over the body
✅ got: (with-two 1 15)
[🧪 test] a let binding wins over the definition it shadows
✅ got: (x 2 10)
[🧪 test] a syntax-case clause binds its pattern variables
✅ got: (a 3 7)
[🧪 test] a pattern variable is not a definition of the file
✅ got: 1
[🧪 test] the ellipsis binds nothing
✅ got: #f
[🧪 test] a literal in the pattern binds nothing
✅ got: #f
+----------------------------------------------+
[📑 suite] files: extensions and filters
[🧪 test] ** crosses a separator
✅ got: #t
[🧪 test] * stops at a separator
✅ got: #f
✅ got: #t
[🧪 test] a pattern is read relative to the root of the walk
✅ got: #t
[🧪 test] a filter replaces the extensions
✅ got: #t
✅ got: #f
[🧪 test] the Scheme extensions sift reads include the library and program ones
[⚙️ assert] .scm is a Lisp file
✅ got: #t
[⚙️ assert] .ss is a Lisp file
✅ got: #t
[⚙️ assert] .sld is a Lisp file
✅ got: #t
[⚙️ assert] .sls is a Lisp file
✅ got: #t
[⚙️ assert] .sps is a Lisp file
✅ got: #t
[⚙️ assert] .el is a Lisp file
✅ got: #t
[⚙️ assert] .lisp is a Lisp file
✅ got: #t
[⚙️ assert] .cl is a Lisp file
✅ got: #t
[⚙️ assert] .asd is a Lisp file
✅ got: #t
[🧪 test] no filter falls back to the extensions
✅ got: #t
✅ got: #f
[🧪 test] a pattern with no separator is matched against the file's own name
✅ got: #t
[🧪 test] the last pattern that matches decides
✅ got: #t
[🧪 test] a dot in a pattern is a dot, not any character
✅ got: #f
[🧪 test] a file sift has no extension for is not one of its files
✅ got: #f
[🧪 test] no filter in the file is no filter at all
✅ got: #f
[🧪 test] a single pattern is a filter with one rule
✅ got: (*.scm)
[🧪 test] a list of patterns is read as it is written
✅ got: (src/** !gen/**)
[🧪 test] a negated pattern takes a file back out
✅ got: #f
✅ got: #t
+----------------------------------------------+
[📑 suite] format: Common Lisp
[🧪 test] a read macro keeps the datum it applies to glued to it
[⚙️ assert] the text matches
✅ got: (defparameter *a* #2A((1 2)))
[⚙️ assert] the text matches
✅ got: (defparameter *c* #c(1 2))
[⚙️ assert] the text matches
✅ got: (probe-file #P"/tmp/x")
[🧪 test] a LOOP keeps its keyword atoms and indents them two in
[⚙️ assert] the text matches
✅ got: (loop :for x :in xs
:do (print x))
[🧪 test] every fixture formats to its expected file
[⚙️ assert] package.lisp formats to its expected file
✅ got: (defpackage :demo
(:use :cl)
(:export #:run))
(in-package :demo)
(defun run (n)
(loop :for i :below n
:do (print i)))
[⚙️ assert] reader-macros.lisp formats to its expected file
✅ got: (in-package :demo)
(defparameter *grid* #2A((1 2)
(3 4)))
(defparameter *z* #c(1 2))
(defparameter *cycle* #1=(a . #1#))
(probe-file #P"/tmp/x")
[🧪 test] a defpackage indents its clauses two columns in
[⚙️ assert] the text matches
✅ got: (defpackage :demo
(:use :cl)
(:export #:run))
[🧪 test] every expected file is a fixed point of formatting
[⚙️ assert] package.lisp is already formatted
✅ got: (defpackage :demo
(:use :cl)
(:export #:run))
(in-package :demo)
(defun run (n)
(loop :for i :below n
:do (print i)))
[⚙️ assert] reader-macros.lisp is already formatted
✅ got: (in-package :demo)
(defparameter *grid* #2A((1 2)
(3 4)))
(defparameter *z* #c(1 2))
(defparameter *cycle* #1=(a . #1#))
(probe-file #P"/tmp/x")
[🧪 test] handler-case clauses align under each other
[⚙️ assert] the text matches
✅ got: (handler-case (foo)
(error (e)
(print e)))
[🧪 test] formatting Common Lisp is idempotent
[⚙️ assert] formatting is a fixed point
✅ got: (defun f (x)
"Doc."
(list x))
[🧪 test] feature conditionals keep both halves on one line
[⚙️ assert] the text matches
✅ got: #+sbcl (defun f ())
#-sbcl (defun f ())
[🧪 test] a defclass indents its slots two columns in
[⚙️ assert] the text matches
✅ got: (defclass point ()
((x :initarg :x)
(y :initarg :y)))
[🧪 test] line endings are normalised to LF
[⚙️ assert] the text matches
✅ got: (a b)
+----------------------------------------------+
[📑 suite] format: Emacs Lisp
[🧪 test] strings, escapes and characters are preserved
[⚙️ assert] the text matches
✅ got: (message "a b\n" ?\C-x)
[🧪 test] the square bracket style does not reach Emacs Lisp
[⚙️ assert] the text matches
✅ got: (cond ((null x) 1)
(t 2))
[🧪 test] use-package keywords do not line up under the package name
[⚙️ assert] the text matches
✅ got: (use-package magit
:ensure t
:bind
("C-x g" . magit-status))
[🧪 test] documented forms the table knows are indented from the opener
[⚙️ assert] the text matches
✅ got: (with-current-buffer buf
(goto-char (point-min)))
[🧪 test] a let binds in a data list, lined up under the first binding
[⚙️ assert] the text matches
✅ got: (let ((a 1)
(b 2))
(+ a b))
[🧪 test] a use-package form puts its keywords and their bodies two columns in
[⚙️ assert] the text matches
✅ got: (use-package evil
:ensure t
:init
(setq evil-want-integration t)
:config
(evil-mode 1))
[🧪 test] every fixture formats to its expected file
[⚙️ assert] buffer.el formats to its expected file
✅ got: ;;; buffer.el --- a demo -*- lexical-binding: t; -*-
(defun my-greet (name)
"Greet NAME."
(message "Hello, %s" name))
(let ((x 1)
(y 2))
(+ x y))
(provide 'buffer)
[⚙️ assert] reader-macros.el formats to its expected file
✅ got: ;;; reader-macros.el --- the read macros of the dialect -*- lexical-binding: t; -*-
(defun my-setup ()
"Set up the table and the keys."
(setq my-table #s(hash-table test equal data ("a" 1)))
(setq my-cycle #1=(a . #1#))
(setq my-keys [?\C-x ?\C-c]))
(provide 'reader-macros)
(setq my-rx (rx (| "a" "b")))
[⚙️ assert] use-package.el formats to its expected file
✅ got: ;;; use-package.el --- a demo -*- lexical-binding: t; -*-
(use-package evil
:ensure t
:init
(setq evil-want-integration t)
:config
(evil-mode 1))
(use-package magit
:ensure t
:bind
("C-x g" . magit-status))
(use-package foo
:ensure t
:custom
(foo-directory "/tmp/foo")
:hook
(prog-mode . foo-mode))
(provide 'use-package-demo)
[🧪 test] condition-case indents its protected form and handlers two in
[⚙️ assert] the text matches
✅ got: (condition-case nil
(foo)
(error (message "no")))
[🧪 test] a data list whose head starts a line is not aligned past it
[⚙️ assert] the text matches
✅ got: (defcustom x
'(
insert-tab))
[🧪 test] a read macro keeps the datum it applies to glued to it
[⚙️ assert] the text matches
✅ got: (defvar t #s(hash-table test equal data ("a" 1)))
[⚙️ assert] the text matches
✅ got: (defvar c #1=(a . #1#))
[🧪 test] a defun indents its docstring and body two columns in
[⚙️ assert] the text matches
✅ got: (defun f (x)
"Return X."
(when x
(message "x")))
[🧪 test] every expected file is a fixed point of formatting
[⚙️ assert] buffer.el is already formatted
✅ got: ;;; buffer.el --- a demo -*- lexical-binding: t; -*-
(defun my-greet (name)
"Greet NAME."
(message "Hello, %s" name))
(let ((x 1)
(y 2))
(+ x y))
(provide 'buffer)
[⚙️ assert] reader-macros.el is already formatted
✅ got: ;;; reader-macros.el --- the read macros of the dialect -*- lexical-binding: t; -*-
(defun my-setup ()
"Set up the table and the keys."
(setq my-table #s(hash-table test equal data ("a" 1)))
(setq my-cycle #1=(a . #1#))
(setq my-keys [?\C-x ?\C-c]))
(provide 'reader-macros)
(setq my-rx (rx (| "a" "b")))
[⚙️ assert] use-package.el is already formatted
✅ got: ;;; use-package.el --- a demo -*- lexical-binding: t; -*-
(use-package evil
:ensure t
:init
(setq evil-want-integration t)
:config
(evil-mode 1))
(use-package magit
:ensure t
:bind
("C-x g" . magit-status))
(use-package foo
:ensure t
:custom
(foo-directory "/tmp/foo")
:hook
(prog-mode . foo-mode))
(provide 'use-package-demo)
[🧪 test] formatting Emacs Lisp is idempotent
[⚙️ assert] formatting is a fixed point
✅ got: (defun f (x)
"Doc."
(list x))
+----------------------------------------------+
[📑 suite] format: Scheme
[🧪 test] moving a verbatim block is idempotent
[⚙️ assert] the shifted block is the same on the second pass
✅ got: (define (f)
#;(ignore
this)
x)
[🧪 test] keyword arguments line up under the first argument
[⚙️ assert] the text matches
✅ got: (make-window title
:width 10
:height 20)
[🧪 test] a project's own indent rule is idempotent
[⚙️ assert] the project rule formats the same way twice
✅ got: (with-my-thing x
y)
[🧪 test] an unknown operator alone on its line indents one column in
[⚙️ assert] the text matches
✅ got: (my-macro
a)
[🧪 test] a read macro keeps the datum it applies to glued to it
[⚙️ assert] the text matches
✅ got: (define a #1=(x . #1#))
[⚙️ assert] the text matches
✅ got: (display #`(a #,b #,@c))
[🧪 test] an R6RS library indents its declarations two columns in
[⚙️ assert] the text matches
✅ got: #!r6rs
(library (demo)
(export f)
(import (rnrs)))
[⚙️ assert] the text matches
✅ got: #!fold-case
(define-library (demo lib)
(import (scheme base))
(export a))
[🧪 test] preserve adds no blank line the author did not write
[⚙️ assert] the text matches
✅ got: (a)
(b)
[🧪 test] a blank line inside a form is kept, but a run is collapsed to two
[⚙️ assert] the text matches
✅ got: (a
b)
[🧪 test] a reader prefix is never separated from its datum
[⚙️ assert] the text matches
✅ got: 'a
[🧪 test] the dangling style puts each closer on its own line
[⚙️ assert] nested.scm formats to its expected file
✅ got: (define (f x)
(let ((a 1)
(b 2)
)
(when (> a b)
(display "yes")
)
)
)
[⚙️ assert] nested.scm is already formatted
✅ got: (define (f x)
(let ((a 1)
(b 2)
)
(when (> a b)
(display "yes")
)
)
)
[🧪 test] a data list lines up under its first element
[⚙️ assert] the text matches
✅ got: (let ((a 1)
(b 2))
(+ a b))
[🧪 test] a multi-line extended symbol keeps the name it was given
[⚙️ assert] the text matches
✅ got: (define #{what
ever}# 1)
[🧪 test] blank lines between top-level forms are collapsed to one
[⚙️ assert] the text matches
✅ got: (a)
(b)
[🧪 test] a cond whose clauses start on their own lines indents them two in
[⚙️ assert] the text matches
✅ got: (cond
[(< n 0) 1]
[else 2])
[🧪 test] formatting is idempotent on this sentence's own source
[⚙️ assert] formatting is a fixed point
✅ got: (define (f x) (progn (a) (b)))
[🧪 test] a vector is closed with the delimiter it was opened with
[⚙️ assert] the text matches
✅ got: (define v #(a b))
[🧪 test] every fixture formats to its expected file
[⚙️ assert] comments.scm formats to its expected file
✅ got: ;;; A file about comments.
(define (f x) ; inline
;; standalone
x) ; trailing
;; a comment after a blank line
(display "text")
[⚙️ assert] messy.scm formats to its expected file
✅ got: (define (square x)
(* x x))
(define (classify n)
(cond [(< n 0) 'negative]
[(= n 0) 'zero]
[else 'positive]))
(let ((a 1)
(b 2))
(+ a b (* a b)))
[⚙️ assert] reader-macros.scm formats to its expected file
✅ got: '(a b)
`(c ,d ,@e)
#(1 2 3) #u8(1 2)
#;(ignored form)
#| block |#
#+(or a b) (display "x")
(define table #(one two
three))
(define bytes #vu8(1 2))
(define #{odd name}# 'x)
(define-syntax (m stx)
(syntax-case stx ()
[(_ x) #`(list #,x ,x)]))
(define (f lst' x'') (list lst' x''))
[🧪 test] an extended symbol is one token, and is never respelled
[⚙️ assert] the text matches
✅ got: (define #{foo bar}# 1)
[🧪 test] a project that writes parentheses keeps them
[⚙️ assert] the text matches
✅ got: (cond ((< n 0) 'negative)
(else 'positive))
[🧪 test] two forms on one line are separated when asked
[⚙️ assert] the text matches
✅ got: (a)
(b)
[🧪 test] a datum comment that moves left keeps its internal shape
[⚙️ assert] the text matches
✅ got: (let ((a 1))
#;(b
c)
a)
[🧪 test] a vector keeps its own opener whatever the bracket style is
[⚙️ assert] the text matches
✅ got: #(1 2 3)
[🧪 test] one blank line is the most a body keeps when asked
[⚙️ assert] the text matches
✅ got: (a
b)
[🧪 test] cond clauses are written with square brackets
[⚙️ assert] the text matches
✅ got: (cond [(< n 0) 'negative]
[(= n 0) 'zero]
[else 'positive])
[🧪 test] a file without a final newline keeps that shape
[⚙️ assert] the text matches
✅ got: (a b)
[🧪 test] a heading comment stays with the form it heads
[⚙️ assert] the text matches
✅ got: (a)
;;; b
(b)
[🧪 test] the one-blank-line style is a fixed point
[⚙️ assert] the text matches
✅ got: (a)
(b)
[🧪 test] a vector's elements line up under its first, symbol or not
[⚙️ assert] the text matches
✅ got: (define v #(foo bar
baz))
[🧪 test] strings are never reflowed or respelled
[⚙️ assert] the text matches
✅ got: (display "a b\n")
[🧪 test] a list whose first element starts a line indents one column in
[⚙️ assert] the text matches
✅ got: '(
insert-tab)
[🧪 test] a comment keeps the line it was on
[⚙️ assert] the text matches
✅ got: (a ; inline
b)
[🧪 test] a single-line datum comment is untouched
[⚙️ assert] the text matches
✅ got: (a #;(b c) d)
[🧪 test] comments are aligned when asked
[⚙️ assert] the text matches
✅ got: (let ((a 1) ; one
(b 22)) ; two
(+ a b))
[🧪 test] indentation follows the operator's rule
[⚙️ assert] the text matches
✅ got: (define (f x)
(let ((a 1))
(if x
a
x)))
[🧪 test] preserving brackets leaves each clause as it was written
[⚙️ assert] the text matches
✅ got: (cond ((< n 0) 1)
[else 2])
[🧪 test] one blank line separates adjacent top-level forms when asked
[⚙️ assert] the text matches
✅ got: (a)
(b)
[🧪 test] an unknown operator lines its arguments up under the first
[⚙️ assert] the text matches
✅ got: (my-macro a
b)
[🧪 test] a call without keywords lines up the same way
[⚙️ assert] the text matches
✅ got: (make-window title
width
height)
[🧪 test] a bytevector's numbers line up under the first as well
[⚙️ assert] the text matches
✅ got: (define b #u8(1 2
3))
[⚙️ assert] the text matches
✅ got: (define b #vu8(1 2
3))
[🧪 test] a multi-line datum comment moves with the code around it
[⚙️ assert] the text matches
✅ got: (define (f)
#;(ignore
this)
x)
[🧪 test] a project's own indent rule wins over the table
[⚙️ assert] the text matches
✅ got: (with-my-thing x
y)
[🧪 test] every expected file is a fixed point of formatting
[⚙️ assert] comments.scm is already formatted
✅ got: ;;; A file about comments.
(define (f x) ; inline
;; standalone
x) ; trailing
;; a comment after a blank line
(display "text")
[⚙️ assert] messy.scm is already formatted
✅ got: (define (square x)
(* x x))
(define (classify n)
(cond [(< n 0) 'negative]
[(= n 0) 'zero]
[else 'positive]))
(let ((a 1)
(b 2))
(+ a b (* a b)))
[⚙️ assert] reader-macros.scm is already formatted
✅ got: '(a b)
`(c ,d ,@e)
#(1 2 3) #u8(1 2)
#;(ignored form)
#| block |#
#+(or a b) (display "x")
(define table #(one two
three))
(define bytes #vu8(1 2))
(define #{odd name}# 'x)
(define-syntax (m stx)
(syntax-case stx ()
[(_ x) #`(list #,x ,x)]))
(define (f lst' x'') (list lst' x''))
[🧪 test] the body of a clause indents two columns
[⚙️ assert] the text matches
✅ got: (cond [else
1])
+----------------------------------------------+
[📑 suite] gexps
[🧪 test] formatting a gexp is a fixed point
[⚙️ assert] formatting is a fixed point
✅ got: #~(mkdir #$output #$(file-append coreutils "/bin/ls"))
[🧪 test] `#$` is a prefix, not part of the atom
✅ got: ((list (#{#$}# output)))
[🧪 test] `#$@` splices a list
✅ got: ((#{#$@}# (list 1)))
[🧪 test] `#+` and `#+@` are gexp prefixes in Scheme
✅ got: ((#{#+}# coreutils))
✅ got: ((#{#+@}# (list 1)))
[🧪 test] `#+` stays a conditional in Common Lisp
✅ got: ()
[🧪 test] a formatted gexp is left alone
[⚙️ assert] the text matches
✅ got: #~(use-modules (guix build utils))
[🧪 test] `#~` is a prefix on the datum it makes
✅ got: ((#{#~}# (mkdir output)))
[🧪 test] the body of a gexp is read as code
[⚙️ assert] the findings are where they should be
✅ got: ((1 4))
[🧪 test] a prefix is glued to its datum, and none is followed by a space
[⚙️ assert] the text matches
✅ got: (list #$output #$@(list 1))
+----------------------------------------------+
[📑 suite] JSON
[🧪 test] the position of an error counts lines from one
[⚙️ assert] the document is refused: it is refused
✅ got: #t
[⚙️ assert] the document is refused: on line 3
✅ got: 3
[⚙️ assert] the document is refused: at column 1
✅ got: 1
[🧪 test] whitespace between tokens is not part of the value
[⚙️ assert] the document is written back the same
✅ got: {"a":[1,2]}
[🧪 test] trailing text after the value is refused
[⚙️ assert] the document is refused: it is refused
✅ got: #t
[⚙️ assert] the document is refused: on line 1
✅ got: 1
[⚙️ assert] the document is refused: at column 4
✅ got: 4
[🧪 test] the escapes JSON requires are read back as characters
[⚙️ assert] the text matches
✅ got: a"b\c
d e
[🧪 test] an object keeps the order it was written in
[⚙️ assert] the document is written back the same
✅ got: {"jsonrpc":"2.0","id":1,"method":"initialize"}
[🧪 test] a bare word is refused
[⚙️ assert] the document is refused: it is refused
✅ got: #t
[⚙️ assert] the document is refused: on line 1
✅ got: 1
[⚙️ assert] the document is refused: at column 2
✅ got: 2
[🧪 test] a symbol names a member as well as a string does
✅ got: 1
[🧪 test] a missing comma is refused
[⚙️ assert] the document is refused: it is refused
✅ got: #t
[⚙️ assert] the document is refused: on line 1
✅ got: 1
[⚙️ assert] the document is refused: at column 4
✅ got: 4
[🧪 test] a \u escape becomes the character it names
[⚙️ assert] the text matches
✅ got: é
[🧪 test] an escaped solidus is a solidus
[⚙️ assert] the text matches
✅ got: a/b
[🧪 test] a nested document round trips
[⚙️ assert] the document is written back the same
✅ got: {"params":{"capabilities":{"textDocument":{"formatting":{}}}}}
[🧪 test] an unterminated string is refused
[⚙️ assert] a malformed member name: it is refused
✅ got: #t
[⚙️ assert] a malformed member name: on line 1
✅ got: 1
[⚙️ assert] a malformed member name: at column 6
✅ got: 6
[🧪 test] a lone surrogate does not raise
[⚙️ assert] the text matches
✅ got: �x
[🧪 test] a trailing comma is refused
[⚙️ assert] an object with a trailing comma: it is refused
✅ got: #t
[⚙️ assert] an object with a trailing comma: on line 1
✅ got: 1
[⚙️ assert] an object with a trailing comma: at column 8
✅ got: 8
[🧪 test] an empty object is not an empty array
[⚙️ assert] the document is written back the same
✅ got: {}
[⚙️ assert] the document is written back the same
✅ got: []
[🧪 test] an array of mixed values round trips
[⚙️ assert] the document is written back the same
✅ got: [1,-2500,true,false,null,"a"]
[🧪 test] a member is found by its name, or a default is answered
✅ got: 1
✅ got: missing
[⚙️ assert] the text matches
✅ got: [1,2]
[🧪 test] a surrogate pair becomes one character
[⚙️ assert] the text matches
✅ got: 😀
[🧪 test] a string that needs escaping is written escaped
[⚙️ assert] the text matches
✅ got: "a\"b\\c\nd"
[🧪 test] a number that is not finite is written as null
[⚙️ assert] the text matches
✅ got: null
[🧪 test] a control character is written as an escape
[⚙️ assert] the text matches
✅ got: "\u0001"
[🧪 test] an object is not an array, and neither is a list
✅ got: #t
✅ got: #t
✅ got: #t
✅ got: #t
[🧪 test] numbers are written the way they are read
[⚙️ assert] 0 round trips
✅ got: 0
[⚙️ assert] 1 round trips
✅ got: 1
[⚙️ assert] -1 round trips
✅ got: -1
[⚙️ assert] 2500 round trips
✅ got: 2500
[⚙️ assert] -2500 round trips
✅ got: -2500
[⚙️ assert] 1.5 round trips
✅ got: 1.5
[⚙️ assert] 0.25 round trips
✅ got: 0.25
+----------------------------------------------+
[📑 suite] language server
[🧪 test] shutdown is answered and exit ends the session
✅ got: 0
✅ got: null
[🧪 test] an expression can be extracted to a procedure
✅ got: refactor.extract
[⚙️ assert] the expression is replaced by the call
✅ got: (extracted w h)
[⚙️ assert] and the procedure takes the enclosing parameters
✅ got: (define (extracted w h)
[🧪 test] the server says what it did in the editor's log
[⚙️ assert] the server logged something
✅ got: #t
[⚙️ assert] as information, not as a complaint
✅ got: 3
[⚙️ assert] and named the findings it published
✅ got: #t
[🧪 test] signature help counts the arguments already written
[⚙️ assert] one argument is finished, so the second is being written
✅ got: 1
[🧪 test] the settings are read again when the client says they changed
✅ got: 0
[⚙️ assert] the buffer was checked against the new settings
✅ got: 2
[⚙️ assert] and the editor can see that it happened
✅ got: #t
[🧪 test] a request before initialize is refused by the protocol's rule
[⚙️ assert] the server says it has not been initialized
✅ got: -32002
[🧪 test] a Common Lisp defparameter is a definition
✅ got: 0
✅ got: 14
[🧪 test] the highlights mark the declaration apart from the uses
✅ got: 2
[⚙️ assert] the declaration is a write
✅ got: 3
[⚙️ assert] the use is a read
✅ got: 2
[🧪 test] organizing imports puts the specs in order
✅ got: source.organizeImports
[⚙️ assert] the library that sorts first is written first
✅ got: (import (scheme base) (srfi 1))
(display 1)
[🧪 test] a code action offers the rule's own fix
[⚙️ assert] an action was offered
✅ got: #t
✅ got: quickfix
✅ got: SIFT012
[⚙️ assert] the fix is the one that turns if into when
✅ got: when
[🧪 test] a client that asks for quickfixes gets quickfixes and nothing else
[⚙️ assert] something was offered
✅ got: #t
[⚙️ assert] no rewrite and no fix-all were mixed in
✅ got: (quickfix)
[🧪 test] a setting the client sends that sift does not have is reported
[⚙️ assert] the editor can see that the setting went nowhere
✅ got: #t
[🧪 test] completion puts the name being typed first
[⚙️ assert] the prefix match is offered first
✅ got: alpha-one
[⚙️ assert] and its sort text says why
✅ got: alpha-one
[🧪 test] the project chooses which kinds of hint it gets
[⚙️ assert] types alone means no parameter names
✅ got: (1)
[🧪 test] an Emacs Lisp defun is a definition
✅ got: 0
[⚙️ assert] `greet' behind the `defun'
✅ got: 7
[🧪 test] initialize names the capabilities sift offers
✅ got: 0
[⚙️ assert] a change replaces the whole buffer
✅ got: 1
[⚙️ assert] the server hears about a buffer opening and closing
✅ got: true
[⚙️ assert] and about a save, which is what refreshes the project
✅ got: #t
[⚙️ assert] the server formats
✅ got: true
[⚙️ assert] the server offers fixes, extractions, the one rewrite it can make, and import sorting
✅ got: #(quickfix refactor.extract refactor.inline refactor.rewrite source.fixAll source.fixAll.sift source.organizeImports)
[⚙️ assert] the server answers a hover
✅ got: true
[🧪 test] signature help answers with the definition's own formal list
✅ got: (greet name)
[⚙️ assert] the cursor is in the first argument
✅ got: 0
[⚙️ assert] the docstring comes with it
✅ got: Greet NAME.
[🧪 test] signature help says nothing about a call sift cannot see
[⚙️ assert] no invented signature
✅ got: null
[🧪 test] a save asks the server to look at the buffer again
✅ got: 0
[⚙️ assert] the buffer is reported, and reported again after the save
✅ got: 2
[🧪 test] a change republishes the findings of the new text
✅ got: 0
[⚙️ assert] the clean text has nothing to report
✅ got: 0
[🧪 test] a keyword argument is not hinted
[⚙️ assert] only the positional argument is named
✅ got: (name )
[🧪 test] signature help answers for a procedure that takes nothing
[⚙️ assert] one name, and no arguments
✅ got: (now)
[🧪 test] exit without a shutdown ends with the status the protocol asks for
✅ got: 1
[🧪 test] a column is counted in the units the protocol counts
[⚙️ assert] the trailing whitespace was found
✅ got: #t
[⚙️ assert] the emoji counted as the two units it is
✅ got: 13
[🧪 test] completion offers the names the project defines
[⚙️ assert] from this buffer
✅ got: #t
[⚙️ assert] from the one next to it
✅ got: #t
[🧪 test] a change sent as a range is applied to the text
✅ got: 0
[⚙️ assert] the `if` the range replaced is gone
✅ got: ()
[🧪 test] the dialect layer still answers about a buffer sift cannot finish
✅ got: 0
[⚙️ assert] a code action array came back
✅ got: #t
[🧪 test] a setting the client sends with initialize is the configuration too
[⚙️ assert] the session started with the editor's settings
✅ got: 0
[🧪 test] a definition in another buffer is found
✅ got: 1
[⚙️ assert] the jump leaves the buffer it started in
✅ got: file:///tmp/sift-lsp-test-lib.scm
✅ got: 9
[🧪 test] an expression can be extracted to a let binding
[⚙️ assert] an extraction was offered
✅ got: #t
✅ got: refactor.extract
[⚙️ assert] the expression was hoisted into a binding
✅ got: (let ((value (* w h))) (+ value 1))
[🧪 test] a lambda can be extracted to a procedure of its own
[⚙️ assert] the lambda was offered as a procedure
✅ got: #t
[⚙️ assert] the name takes the lambda's place
✅ got: procedure
[⚙️ assert] and the definition keeps the lambda's own formals
✅ got: (define (procedure x)
[⚙️ assert] and its body, as it was written
✅ got: (* x x)
[🧪 test] one action fixes every safe finding in the buffer
[⚙️ assert] one action, not one per finding
✅ got: 1
✅ got: source.fixAll.sift
[⚙️ assert] the `if' was rewritten
✅ got: when
[⚙️ assert] and the trailing whitespace went with it
✅ got: #f
[🧪 test] an unknown method is refused and the server keeps its answers
✅ got: -32601
[⚙️ assert] shutdown and exit end the server with 0
✅ got: 0
[🧪 test] a call to a single-expression procedure can be inlined
✅ got: refactor.inline
[⚙️ assert] the argument took the parameter's place
✅ got: (* 3 3)
[🧪 test] the name of a parameter is its own definition
[⚙️ assert] a request on the binding answers with the binding
✅ got: 1
✅ got: 11
[🧪 test] a symbol with no definition answers with nothing at all
[⚙️ assert] `f' is defined, so this is the definition
✅ got: 1
[⚙️ assert] a name nothing defines is an empty answer, not an error
✅ got: 0
[🧪 test] opening a buffer publishes its findings
✅ got: 0
[⚙️ assert] the if has no else branch
✅ got: #t
[⚙️ assert] a warning is a warning
✅ got: 2
[🧪 test] a client that asks for quickfixes gets no extraction
[⚙️ assert] no extraction was mixed in
✅ got: #f
[🧪 test] prepareRename says what would be renamed, and rename edits every mention
✅ got: f
✅ got: 1
[⚙️ assert] the definition and the call
✅ got: 2
✅ got: g
[⚙️ assert] the edit is pinned to the version it was computed from
✅ got: 1
[🧪 test] the same text is not checked twice
[⚙️ assert] one buffer, one publication
✅ got: 1
[🧪 test] closing a buffer takes its findings away
[⚙️ assert] the last word about the file is that it has no findings
✅ got: 0
[🧪 test] references list every mention in the project
[⚙️ assert] the definition and the use
✅ got: 2
[⚙️ assert] this buffer's mention first, then the other one's
✅ got: (file:///tmp/sift-lsp-test.scm file:///tmp/sift-lsp-test-lib.scm)
[🧪 test] the editor's settings are part of the configuration
[⚙️ assert] a setting the server does not have a file for is not a failure
✅ got: 0
[⚙️ assert] and turning the hints off turns them off
✅ got: 0
[🧪 test] a call sift cannot inline is left alone
[⚙️ assert] refused rather than approximated
✅ got: 0
[🧪 test] a message that is not JSON is answered, and the session goes on
[⚙️ assert] the server exited cleanly
✅ got: 0
[⚙️ assert] initialize was answered
✅ got: #t
[⚙️ assert] the request after the bad message was answered too
✅ got: #t
[🧪 test] formatting answers with the text sift would write
[⚙️ assert] one edit came back
✅ got: #t
[⚙️ assert] the edit is the buffer, indented
✅ got: (if (ready?)
[🧪 test] a parameter list is not a call to the procedure it defines
✅ got: 0
[🧪 test] a notification that raises does not take the server with it
[⚙️ assert] the editor was told the request was not usable
✅ got: #t
[⚙️ assert] and the next request was answered normally
✅ got: null
[🧪 test] a name says nothing about its type
[⚙️ assert] only the argument whose type is written down
✅ got: (number )
[🧪 test] the dialect follows the language identifier the editor sent
[⚙️ assert] the rule that only Emacs Lisp has fired
✅ got: #t
[🧪 test] an import that is already organized has no action
[⚙️ assert] nothing to offer, and nothing offered
✅ got: 0
[🧪 test] inlay hints name the positional arguments of a call
✅ got: 0
[⚙️ assert] one hint per argument, named by the definition
✅ got: (parent width height title )
[⚙️ assert] and each one is a parameter, which is how an editor styles it
✅ got: 2
[🧪 test] a symbol jumps to the definition that names it
[⚙️ assert] one definition, not every `square' in the file
✅ got: 1
✅ got: 0
✅ got: 9
[🧪 test] a configuration the server was started with is what it answers with
[⚙️ assert] a warning is below the severity the server was given
✅ got: 0
[🧪 test] the outline nests a definition inside the one that holds it
✅ got: 1
✅ got: f
[⚙️ assert] `g' is inside `f', not beside it
✅ got: 1
✅ got: g
[🧪 test] an unknown request is refused, and the server keeps talking
[⚙️ assert] the method is not implemented
✅ got: -32601
[⚙️ assert] the next request was still answered
✅ got: #t
[🧪 test] workspace/symbol searches the buffers the editor has open
✅ got: 1
✅ got: square
[🧪 test] a buffer that does not parse has findings, not silence
✅ got: 0
[⚙️ assert] the file that never closes is reported as an error
✅ got: #t
[⚙️ assert] and the finding is named, not anonymous
✅ got: #t
[🧪 test] formatting a buffer that does not parse says why instead of nothing
✅ got: 0
[⚙️ assert] no edit is offered, because sift does not guess
✅ got: 0
[⚙️ assert] the editor is told that formatting was refused
✅ got: #t
[⚙️ assert] as an error
✅ got: 1
✅ got: cannot format
[🧪 test] a finding carries the range an editor highlights
[⚙️ assert] the if is on the second line, counted from zero
✅ got: 1
[⚙️ assert] at the column the `if` itself is in
✅ got: 3
[🧪 test] a file changed on disk is a reason to check the open buffers
✅ got: 0
[⚙️ assert] the open buffer is still answered for
✅ got: #t
[🧪 test] organizing imports removes the ones nothing uses
[⚙️ assert] the unused import went, and the file still reads
✅ got: (import (scheme base))
(display 1)
[🧪 test] a jump is answered from the project when the client names a root
✅ got: 0
[⚙️ assert] the file that defines the name was found
✅ got: #t
[⚙️ assert] and it is the file on disk, not a buffer
✅ got: file:///tmp/sift-test-2904-262/other.scm
✅ got: 0
[🧪 test] the hover describes the symbol rather than the line
✅ got: **square**
✅ got: function
[⚙️ assert] the definition's own docstring, not the rule's
✅ got: Square X.
[🧪 test] a rename that is not a symbol name is refused, not written
✅ got: -32602
[🧪 test] a client with no language for the file still gets its findings
✅ got: 0
[⚙️ assert] the finding was published from the file's own extension
✅ got: #t
[⚙️ assert] and nothing was wrong enough to interrupt anybody
✅ got: #t
[🧪 test] a reference inside a let jumps to the binding, not the outer name
[⚙️ assert] the `let' binding, on the second line
✅ got: 1
✅ got: 9
[🧪 test] new text is checked again even when its findings look the same
[⚙️ assert] the new text was reported
✅ got: 2
[⚙️ assert] and the finding moved with the text around it
✅ got: 2
[🧪 test] the hover says what the rule wants
✅ got: SIFT012
✅ got: if-without-else
[🧪 test] a call sift cannot resolve gets no inlay hint
[⚙️ assert] an invented name would be worse than none
✅ got: 0
[🧪 test] a literal's type is hinted when the project asks for it
[⚙️ assert] the parameters are named, as before
✅ got: (parent width title )
[⚙️ assert] and a literal says its own type
✅ got: (number string )
[🧪 test] an inlay hint sits where its argument starts
[⚙️ assert] on the line of the call, counted from zero
✅ got: 3
✅ got: name
[🧪 test] the definition under the cursor can be reformatted on its own
✅ got: refactor.rewrite
[⚙️ assert] the body was indented
✅ got: (* x x))
[⚙️ assert] the edit starts at the definition
✅ got: 0
[⚙️ assert] and ends with it, leaving the next definition alone
✅ got: 1
[🧪 test] initialize advertises the navigation requests
[⚙️ assert] definitions
✅ got: true
[⚙️ assert] references
✅ got: true
[⚙️ assert] highlights
✅ got: true
[⚙️ assert] an outline
✅ got: true
[⚙️ assert] a workspace search
✅ got: true
[⚙️ assert] a rename, with a pre-flight check
✅ got: true
+----------------------------------------------+
[📑 suite] pool: many files, one order
[🧪 test] one worker answers what many workers answer
[⚙️ assert] the same answers, however they were spread
✅ got: (0 0 1 3 6 10 15 21 21 22 24 27 31 36 42 42 43 45 48 52 57 63 63 64 66 69 73 78 84 84 85 87 90 94 99 105 105 106 108 111)
[🧪 test] the answers are in the order the work was given
[⚙️ assert] the order is the order of the items
✅ got: (0 1 4 9 16 25 36 49)
[🧪 test] an error reaches the caller instead of vanishing in a thread
[⚙️ assert] the caller sees the error the work raised
✅ success catching error: misc-error: (#f no ~S (5) #f)
[🧪 test] the error is the one the work raised, not a summary of it
[⚙️ assert] the key and its arguments arrive unchanged
✅ got: (0 1 2)
[🧪 test] the empty list is answered without a thread
✅ got: ()
+----------------------------------------------+
[📑 suite] reader: Common Lisp
[🧪 test] a LOOP form is read as ordinary forms
[⚙️ assert] the text matches
✅ got: (loop :for x :in xs :do (print x))
[🧪 test] a structure literal is a prefix over a list
[⚙️ assert] the text matches
✅ got: #s(point :x 1 :y 2)
[🧪 test] a pathname is a prefix over a string
[⚙️ assert] the text matches
✅ got: (probe-file #p"/tmp/x")
[🧪 test] radix and exactness prefixes are kept
[⚙️ assert] the text matches
✅ got: (list #x1F #o17 #b1010 #e1.0)
[🧪 test] a Common Lisp file round-trips byte for byte
[⚙️ assert] the text matches
✅ got: (defpackage :demo (:use :cl) (:export #:run))
(in-package :demo)
(defun run ()
"Run it."
(format t "~a~%" 1))
[🧪 test] a datum comment is Scheme syntax, and is reported here
✅ got: ((1 1 the))
[🧪 test] block comments nest
[⚙️ assert] the text matches
✅ got: #| a #| b |# c |# x
[🧪 test] a keyword is an atom of its own kind
✅ got: (keyword)
[🧪 test] a read macro keeps its datum glued to it
[⚙️ assert] the text matches
✅ got: #2A((1 2) (3 4))
[⚙️ assert] the text matches
✅ got: #c(1 2)
[⚙️ assert] the text matches
✅ got: #1=(a . #1#)
[⚙️ assert] the text matches
✅ got: #*1011
[🧪 test] an unreadable object is copied verbatim
[⚙️ assert] the text matches
✅ got: #<buffer foo>
[⚙️ assert] the text matches
✅ got: (describe #<window 1 on foo>)
[🧪 test] a bracket and a hash are symbol characters here
✅ got: (A[B A#B)
[⚙️ assert] the text matches
✅ got: (defun f () A[B)
[🧪 test] read-time evaluation is copied and not evaluated
[⚙️ assert] the text matches
✅ got: #.(+ 1 2)
✅ got: (#.(+ 1 2))
[🧪 test] a feature expression may be a list
[⚙️ assert] the text matches
✅ got: #+(or sbcl ccl) (defun f ())
[🧪 test] no parse error is reported for Common Lisp syntax
✅ got: ()
[🧪 test] a negated feature conditional is kept
[⚙️ assert] the text matches
✅ got: #-(not sbcl) (defun f ())
[🧪 test] a case-sensitive symbol keeps its case
[⚙️ assert] the text matches
✅ got: (defun make-Thing () (list :Thing))
[🧪 test] a datum comment holds one datum
[⚙️ assert] the text matches
✅ got: #;foo bar
[🧪 test] a quote ends a symbol here
✅ got: (a)
[🧪 test] package markers are kept apart
✅ got: ((foo:bar . foo:) (foo::baz . foo::) (:key . #f) (#:uninterned . #:))
[🧪 test] a feature conditional keeps both halves
✅ got: ((feature sbcl) (form (defun f ())))
[🧪 test] a pathname keeps the case of its dispatch character
[⚙️ assert] the text matches
✅ got: (probe-file #P"/tmp/x")
✅ got: ()
+----------------------------------------------+
[📑 suite] reader: Emacs Lisp
[🧪 test] a datum comment is reported, and still kept
✅ got: ((1 1 the))
[⚙️ assert] the text matches
✅ got: #;foo bar
[🧪 test] an Emacs Lisp file round-trips byte for byte
[⚙️ assert] the text matches
✅ got: ;;; demo.el --- a demo -*- lexical-binding: t; -*-
(defun demo (x)
"Return X."
(message "%s" x))
(provide 'demo)
[🧪 test] a Scheme character literal is reported, and still kept
✅ got: ((1 1 character))
[⚙️ assert] the text matches
✅ got: #\a
[🧪 test] a hash-table literal is a read macro over a list
[⚙️ assert] the text matches
✅ got: (defvar t #s(hash-table test equal data ("a" 1)))
[🧪 test] a read-circle label is a prefix over its datum
[⚙️ assert] the text matches
✅ got: #1=(a . #1#)
[🧪 test] a brace is a symbol character, not a bracket
✅ got: ({ _ })
[🧪 test] character literals keep their spelling
✅ got: (?a ?\n ?\C-x ?\M-x ?\s ?\()
[🧪 test] vectors are read as vectors
✅ got: (#(1 2 3))
[🧪 test] a backslash quotes the next character of a symbol
✅ got: ()
✅ got: (\( \) a\#b)
[🧪 test] the dialect is detected from the extension
✅ got: elisp
[🧪 test] a character literal with a meta and a control modifier is one atom
✅ got: (?\M-\C-x)
[🧪 test] a dotted pair keeps its dot
[⚙️ assert] the text matches
✅ got: (a . b)
[🧪 test] the lexical-binding header is an ordinary comment
[⚙️ assert] the text matches
✅ got: ;;; foo.el --- a package -*- lexical-binding: t; -*-
[🧪 test] a function quote is a prefix, like a quote
✅ got: ((function foo) (quote bar))
[🧪 test] a bar is an ordinary symbol character, not an escape
✅ got: ()
✅ got: (| a b)
[🧪 test] the dialect is detected from a lexical-binding marker
✅ got: elisp
[🧪 test] docstrings with escapes are not respelled
[⚙️ assert] the text matches
✅ got: (defun f ()
"Say \"hi\"."
nil)
[🧪 test] a shebang line is kept
[⚙️ assert] the text matches
✅ got: #!/usr/bin/env emacs --script
(message "hi")
[🧪 test] a block comment is reported, and still kept
✅ got: ((1 1 block))
[⚙️ assert] the text matches
✅ got: #| not elisp |# x
[🧪 test] a defun keeps its name, argument list, docstring and body
✅ got: ((defun add (a b) "Add A and B." (+ a b)))
+----------------------------------------------+
[📑 suite] reader: Scheme
[🧪 test] an extended symbol round-trips, newline and escape included
[⚙️ assert] the text matches
✅ got: (define #{what
ever}# 1)
[⚙️ assert] the text matches
✅ got: '#{a\}b}#
[🧪 test] every reader prefix applies to one datum
✅ got: ((quote a) (quasiquote (b (unquote c) (unquote-splicing d))) (function e))
[🧪 test] a shebang names which Scheme is running the file
✅ got: scheme
✅ got: scheme
✅ got: scheme
[🧪 test] an inline comment knows it follows code
✅ got: (#f #t)
[🧪 test] a syntax-case prefix is a prefix, and its datum is glued to it
✅ got: ()
✅ got: #`
✅ got: a
✅ got: #,
✅ got: #,@
[⚙️ assert] the text matches
✅ got: (display #`(a #,b #,@c))
[🧪 test] a quote or a comma inside a symbol belongs to it
✅ got: (define x' 1)
✅ got: (list lst'' a,b)
[⚙️ assert] the text matches
✅ got: (define x' 1)
[🧪 test] the datum comment may hold a datum with a datum comment
[⚙️ assert] the text matches
✅ got: #;#;a b c
[🧪 test] blank lines are nodes, so they survive a round trip
[⚙️ assert] the text matches
✅ got: (a)
(b)
[🧪 test] a prefix separated from its datum still reads
✅ got: ((quote a))
[🧪 test] CRLF is read as one newline per line
[⚙️ assert] the text matches
✅ got: (a
b)
[🧪 test] top-level atoms keep their kind
✅ got: (symbol keyword number number string character)
[🧪 test] a dotted pair keeps its dot as an atom
[⚙️ assert] the text matches
✅ got: (a . b)
✅ got: (a . b)
[🧪 test] an unmatched closer is reported, and the rest of the file is read
✅ got: ((1 2 unmatched))
✅ got: (a ) b)
[🧪 test] a shebang is a node, not a reader directive
[⚙️ assert] the text matches
✅ got: #!/usr/bin/env guile
(foo)
[🧪 test] an extended symbol is a symbol even when it looks like a number
✅ got: (#{}# #{4242}#)
✅ got: (symbol symbol)
[🧪 test] a Chez directive inside a form is an atom
✅ got: ()
[⚙️ assert] the text matches
✅ got: (lambda (x #!optional y) x)
[🧪 test] a whole file of trivia round-trips byte for byte
[⚙️ assert] the text matches
✅ got: ;; a comment
;; another
[🧪 test] a vector node knows it is a vector, and a bracket is one only in Elisp
[⚙️ assert] a `#(' literal
✅ got: #t
✅ got: #(
[⚙️ assert] a Scheme clause written with a bracket
✅ got: #f
[⚙️ assert] an Emacs Lisp vector
✅ got: #t
[🧪 test] a read macro over a glued datum is one node
✅ got: ()
✅ got: prefix
✅ got: #1=
[⚙️ assert] the text matches
✅ got: #S(point :x 1)
[🧪 test] a file that is already formatted round-trips byte for byte
[⚙️ assert] the text matches
✅ got: (define (square x)
(* x x))
;; done
[🧪 test] read-time evaluation is Common Lisp syntax, and is reported
✅ got: ((1 1 read-time))
[⚙️ assert] the text matches
✅ got: #.(+ 1 2)
[🧪 test] nested prefixes stay on the datum they belong to
✅ got: ((quote #(1 2)))
✅ got: ((quote (quasiquote (a (unquote b)))))
[🧪 test] character literals keep their spelling
✅ got: (#\a #\space #\newline #\x41)
[🧪 test] numbers are not normalised
✅ got: (16 5 1 1/3 1.0e10)
[🧪 test] the reader marks everything inside a datum comment
[⚙️ assert] the datum itself
✅ got: #t
[⚙️ assert] its children
✅ got: #t
[🧪 test] a datum comment inside a list comments out one element
✅ got: ((a c))
[🧪 test] both spellings of a bytevector are the same datum
[⚙️ assert] the text matches
✅ got: (vector-ref #vu8(1 2) 0)
[⚙️ assert] `#vu8(' is a bytevector
✅ got: #t
[🧪 test] comments are kept, every one of them
✅ got: (;; one ;; two ; not three ;; three)
[🧪 test] a reader directive is a token, not a shebang
✅ got: ()
✅ got: atom
✅ got: #!r6rs
[⚙️ assert] the text matches
✅ got: #!fold-case
(a)
[🧪 test] an unterminated form is reported at its opener
✅ got: ((1 1 unterminated))
✅ got: ((a (b c)))
[🧪 test] block comments nest, and none of them is lost
[⚙️ assert] the text matches
✅ got: #| a #| b |# c |# x
[🧪 test] a block comment between two elements is preserved
[⚙️ assert] the text matches
✅ got: (a #| note |# b)
[🧪 test] an unterminated extended symbol is reported at its opener
✅ got: ((1 1 unterminated))
[🧪 test] locations count characters, not bytes
✅ got: 1
✅ got: 4
✅ got: 4
[🧪 test] a Guile extended symbol is one atom, spaces and all
✅ got: ()
✅ got: symbol
✅ got: #{foo bar}#
[🧪 test] a vector keeps the comments written inside it
[⚙️ assert] the text matches
✅ got: #(a #| note |# b)
[🧪 test] string escapes are kept exactly as they were written
[⚙️ assert] the text matches
✅ got: (display "a \" b\n\t\x41;")
[🧪 test] a list is a list of its elements
✅ got: ((a b (c d)))
[🧪 test] a datum comment holds exactly one datum
✅ got: (a b)
[⚙️ assert] the text matches
✅ got: #;foo a
[🧪 test] a brace is a symbol character, not a bracket
✅ got: ()
✅ got: ({a b})
[⚙️ assert] the text matches
✅ got: {a
b}
[🧪 test] an unterminated string is reported at its quote
✅ got: ((1 4 unterminated) (1 1 unterminated))
[🧪 test] a backslash-newline inside a string is kept
[⚙️ assert] the text matches
✅ got: "one \
two"
[🧪 test] extended symbols are Guile syntax, and say so elsewhere
✅ got: ((1 1 extended))
[🧪 test] vectors and bytevectors are read with their own opener
✅ got: (#(1 2 3))
✅ got: #u8(1 2)
+----------------------------------------------+
[📑 suite] robustness
[🧪 test] an empty body is reported rather than raising
✅ got: 1
[🧪 test] formatting an odd source twice changes nothing
[⚙️ assert] idempotent: ""
✅ got:
[⚙️ assert] idempotent: " "
✅ got:
[⚙️ assert] idempotent: "\n\n\n"
✅ got:
[⚙️ assert] idempotent: "("
✅ got: (
[⚙️ assert] idempotent: ")"
✅ got: )
[⚙️ assert] idempotent: "())"
✅ got: ())
[⚙️ assert] idempotent: "(defun)"
✅ got: (defun)
[⚙️ assert] idempotent: "(defun defmacro)"
✅ got: (defun defmacro)
[⚙️ assert] idempotent: "(defun f)"
✅ got: (defun f)
[⚙️ assert] idempotent: "(defun f ()"
✅ got: (defun f ()
[⚙️ assert] idempotent: "(defmacro)"
✅ got: (defmacro)
[⚙️ assert] idempotent: "(let)"
✅ got: (let)
[⚙️ assert] idempotent: "(let ())"
✅ got: (let ())
[⚙️ assert] idempotent: "(case)"
✅ got: (case)
[⚙️ assert] idempotent: "(case x)"
✅ got: (case x)
[⚙️ assert] idempotent: "(case x ())"
✅ got: (case x [])
[⚙️ assert] idempotent: "(case x ((cond) 1))"
✅ got: (case x [(cond) 1])
[⚙️ assert] idempotent: "(cond)"
✅ got: (cond)
[⚙️ assert] idempotent: "(cond ())"
✅ got: (cond [])
[⚙️ assert] idempotent: "(lambda)"
✅ got: (lambda)
[⚙️ assert] idempotent: "(lambda ())"
✅ got: (lambda ())
[⚙️ assert] idempotent: "(define)"
✅ got: (define)
[⚙️ assert] idempotent: "(define ())"
✅ got: (define ())
[⚙️ assert] idempotent: "(quote)"
✅ got: (quote)
[⚙️ assert] idempotent: "'"
✅ got: '
[⚙️ assert] idempotent: "#"
✅ got: #
[⚙️ assert] idempotent: "#;"
✅ got: #;
[⚙️ assert] idempotent: "#|"
✅ got: #|
[⚙️ assert] idempotent: "#\\"
✅ got: #\
[⚙️ assert] idempotent: "?\\"
✅ got: ?\
[⚙️ assert] idempotent: "(a . )"
✅ got: (a .)
[⚙️ assert] idempotent: "(a . b . c)"
✅ got: (a . b . c)
[⚙️ assert] idempotent: "(#)"
✅ got: (#)
[⚙️ assert] idempotent: "(list #;)"
✅ got: (list #;)
[⚙️ assert] idempotent: "(list #|x|#)"
✅ got: (list #|x|#)
[⚙️ assert] idempotent: "(((("
✅ got: ((((
[⚙️ assert] idempotent: "))))"
✅ got: ))))
[⚙️ assert] idempotent: "(f :a 1 :a 2)"
✅ got: (f :a 1 :a 2)
[⚙️ assert] idempotent: "(f \"unterminated"
✅ got: (f "unterminated
[⚙️ assert] idempotent: "(f #<garbage)"
✅ got: (f #<garbage)
[⚙️ assert] idempotent: "(f #.(+ 1 2))"
✅ got: (f #.(+ 1 2))
[⚙️ assert] idempotent: "(let ((x 1) (x 2)) x)"
✅ got: (let ((x 1) (x 2)) x)
[⚙️ assert] idempotent: "(when)"
✅ got: (when)
[⚙️ assert] idempotent: "(unless)"
✅ got: (unless)
[⚙️ assert] idempotent: "(if)"
✅ got: (if)
[⚙️ assert] idempotent: "(do)"
✅ got: (do)
[⚙️ assert] idempotent: "(λ (x) x)"
✅ got: (λ (x) x)
[🧪 test] a case clause whose datum is a list of symbols is not a form
✅ got: ()
[🧪 test] every odd source is read, linted and formatted without raising
[⚙️ assert] scheme: ""
✅ got: #t
[⚙️ assert] scheme: ""
✅ got: #t
[⚙️ assert] scheme: ""
✅ got: #t
[⚙️ assert] scheme: " "
✅ got: #t
[⚙️ assert] scheme: " "
✅ got: #t
[⚙️ assert] scheme: " "
✅ got: #t
[⚙️ assert] scheme: "\n\n\n"
✅ got: #t
[⚙️ assert] scheme: "\n\n\n"
✅ got: #t
[⚙️ assert] scheme: "\n\n\n"
✅ got: #t
[⚙️ assert] scheme: "("
✅ got: #t
[⚙️ assert] scheme: "("
✅ got: #t
[⚙️ assert] scheme: "("
✅ got: #t
[⚙️ assert] scheme: ")"
✅ got: #t
[⚙️ assert] scheme: ")"
✅ got: #t
[⚙️ assert] scheme: ")"
✅ got: #t
[⚙️ assert] scheme: "())"
✅ got: #t
[⚙️ assert] scheme: "())"
✅ got: #t
[⚙️ assert] scheme: "())"
✅ got: #t
[⚙️ assert] scheme: "(defun)"
✅ got: #t
[⚙️ assert] scheme: "(defun)"
✅ got: #t
[⚙️ assert] scheme: "(defun)"
✅ got: #t
[⚙️ assert] scheme: "(defun defmacro)"
✅ got: #t
[⚙️ assert] scheme: "(defun defmacro)"
✅ got: #t
[⚙️ assert] scheme: "(defun defmacro)"
✅ got: #t
[⚙️ assert] scheme: "(defun f)"
✅ got: #t
[⚙️ assert] scheme: "(defun f)"
✅ got: #t
[⚙️ assert] scheme: "(defun f)"
✅ got: #t
[⚙️ assert] scheme: "(defun f ()"
✅ got: #t
[⚙️ assert] scheme: "(defun f ()"
✅ got: #t
[⚙️ assert] scheme: "(defun f ()"
✅ got: #t
[⚙️ assert] scheme: "(defmacro)"
✅ got: #t
[⚙️ assert] scheme: "(defmacro)"
✅ got: #t
[⚙️ assert] scheme: "(defmacro)"
✅ got: #t
[⚙️ assert] scheme: "(let)"
✅ got: #t
[⚙️ assert] scheme: "(let)"
✅ got: #t
[⚙️ assert] scheme: "(let)"
✅ got: #t
[⚙️ assert] scheme: "(let ())"
✅ got: #t
[⚙️ assert] scheme: "(let ())"
✅ got: #t
[⚙️ assert] scheme: "(let ())"
✅ got: #t
[⚙️ assert] scheme: "(case)"
✅ got: #t
[⚙️ assert] scheme: "(case)"
✅ got: #t
[⚙️ assert] scheme: "(case)"
✅ got: #t
[⚙️ assert] scheme: "(case x)"
✅ got: #t
[⚙️ assert] scheme: "(case x)"
✅ got: #t
[⚙️ assert] scheme: "(case x)"
✅ got: #t
[⚙️ assert] scheme: "(case x ())"
✅ got: #t
[⚙️ assert] scheme: "(case x ())"
✅ got: #t
[⚙️ assert] scheme: "(case x ())"
✅ got: #t
[⚙️ assert] scheme: "(case x ((cond) 1))"
✅ got: #t
[⚙️ assert] scheme: "(case x ((cond) 1))"
✅ got: #t
[⚙️ assert] scheme: "(case x ((cond) 1))"
✅ got: #t
[⚙️ assert] scheme: "(cond)"
✅ got: #t
[⚙️ assert] scheme: "(cond)"
✅ got: #t
[⚙️ assert] scheme: "(cond)"
✅ got: #t
[⚙️ assert] scheme: "(cond ())"
✅ got: #t
[⚙️ assert] scheme: "(cond ())"
✅ got: #t
[⚙️ assert] scheme: "(cond ())"
✅ got: #t
[⚙️ assert] scheme: "(lambda)"
✅ got: #t
[⚙️ assert] scheme: "(lambda)"
✅ got: #t
[⚙️ assert] scheme: "(lambda)"
✅ got: #t
[⚙️ assert] scheme: "(lambda ())"
✅ got: #t
[⚙️ assert] scheme: "(lambda ())"
✅ got: #t
[⚙️ assert] scheme: "(lambda ())"
✅ got: #t
[⚙️ assert] scheme: "(define)"
✅ got: #t
[⚙️ assert] scheme: "(define)"
✅ got: #t
[⚙️ assert] scheme: "(define)"
✅ got: #t
[⚙️ assert] scheme: "(define ())"
✅ got: #t
[⚙️ assert] scheme: "(define ())"
✅ got: #t
[⚙️ assert] scheme: "(define ())"
✅ got: #t
[⚙️ assert] scheme: "(quote)"
✅ got: #t
[⚙️ assert] scheme: "(quote)"
✅ got: #t
[⚙️ assert] scheme: "(quote)"
✅ got: #t
[⚙️ assert] scheme: "'"
✅ got: #t
[⚙️ assert] scheme: "'"
✅ got: #t
[⚙️ assert] scheme: "'"
✅ got: #t
[⚙️ assert] scheme: "#"
✅ got: #t
[⚙️ assert] scheme: "#"
✅ got: #t
[⚙️ assert] scheme: "#"
✅ got: #t
[⚙️ assert] scheme: "#;"
✅ got: #t
[⚙️ assert] scheme: "#;"
✅ got: #t
[⚙️ assert] scheme: "#;"
✅ got: #t
[⚙️ assert] scheme: "#|"
✅ got: #t
[⚙️ assert] scheme: "#|"
✅ got: #t
[⚙️ assert] scheme: "#|"
✅ got: #t
[⚙️ assert] scheme: "#\\"
✅ got: #t
[⚙️ assert] scheme: "#\\"
✅ got: #t
[⚙️ assert] scheme: "#\\"
✅ got: #t
[⚙️ assert] scheme: "?\\"
✅ got: #t
[⚙️ assert] scheme: "?\\"
✅ got: #t
[⚙️ assert] scheme: "?\\"
✅ got: #t
[⚙️ assert] scheme: "(a . )"
✅ got: #t
[⚙️ assert] scheme: "(a . )"
✅ got: #t
[⚙️ assert] scheme: "(a . )"
✅ got: #t
[⚙️ assert] scheme: "(a . b . c)"
✅ got: #t
[⚙️ assert] scheme: "(a . b . c)"
✅ got: #t
[⚙️ assert] scheme: "(a . b . c)"
✅ got: #t
[⚙️ assert] scheme: "(#)"
✅ got: #t
[⚙️ assert] scheme: "(#)"
✅ got: #t
[⚙️ assert] scheme: "(#)"
✅ got: #t
[⚙️ assert] scheme: "(list #;)"
✅ got: #t
[⚙️ assert] scheme: "(list #;)"
✅ got: #t
[⚙️ assert] scheme: "(list #;)"
✅ got: #t
[⚙️ assert] scheme: "(list #|x|#)"
✅ got: #t
[⚙️ assert] scheme: "(list #|x|#)"
✅ got: #t
[⚙️ assert] scheme: "(list #|x|#)"
✅ got: #t
[⚙️ assert] scheme: "(((("
✅ got: #t
[⚙️ assert] scheme: "(((("
✅ got: #t
[⚙️ assert] scheme: "(((("
✅ got: #t
[⚙️ assert] scheme: "))))"
✅ got: #t
[⚙️ assert] scheme: "))))"
✅ got: #t
[⚙️ assert] scheme: "))))"
✅ got: #t
[⚙️ assert] scheme: "(f :a 1 :a 2)"
✅ got: #t
[⚙️ assert] scheme: "(f :a 1 :a 2)"
✅ got: #t
[⚙️ assert] scheme: "(f :a 1 :a 2)"
✅ got: #t
[⚙️ assert] scheme: "(f \"unterminated"
✅ got: #t
[⚙️ assert] scheme: "(f \"unterminated"
✅ got: #t
[⚙️ assert] scheme: "(f \"unterminated"
✅ got: #t
[⚙️ assert] scheme: "(f #<garbage)"
✅ got: #t
[⚙️ assert] scheme: "(f #<garbage)"
✅ got: #t
[⚙️ assert] scheme: "(f #<garbage)"
✅ got: #t
[⚙️ assert] scheme: "(f #.(+ 1 2))"
✅ got: #t
[⚙️ assert] scheme: "(f #.(+ 1 2))"
✅ got: #t
[⚙️ assert] scheme: "(f #.(+ 1 2))"
✅ got: #t
[⚙️ assert] scheme: "(let ((x 1) (x 2)) x)"
✅ got: #t
[⚙️ assert] scheme: "(let ((x 1) (x 2)) x)"
✅ got: #t
[⚙️ assert] scheme: "(let ((x 1) (x 2)) x)"
✅ got: #t
[⚙️ assert] scheme: "(when)"
✅ got: #t
[⚙️ assert] scheme: "(when)"
✅ got: #t
[⚙️ assert] scheme: "(when)"
✅ got: #t
[⚙️ assert] scheme: "(unless)"
✅ got: #t
[⚙️ assert] scheme: "(unless)"
✅ got: #t
[⚙️ assert] scheme: "(unless)"
✅ got: #t
[⚙️ assert] scheme: "(if)"
✅ got: #t
[⚙️ assert] scheme: "(if)"
✅ got: #t
[⚙️ assert] scheme: "(if)"
✅ got: #t
[⚙️ assert] scheme: "(do)"
✅ got: #t
[⚙️ assert] scheme: "(do)"
✅ got: #t
[⚙️ assert] scheme: "(do)"
✅ got: #t
[⚙️ assert] scheme: "(λ (x) x)"
✅ got: #t
[⚙️ assert] scheme: "(λ (x) x)"
✅ got: #t
[⚙️ assert] scheme: "(λ (x) x)"
✅ got: #t
[⚙️ assert] elisp: ""
✅ got: #t
[⚙️ assert] elisp: ""
✅ got: #t
[⚙️ assert] elisp: ""
✅ got: #t
[⚙️ assert] elisp: " "
✅ got: #t
[⚙️ assert] elisp: " "
✅ got: #t
[⚙️ assert] elisp: " "
✅ got: #t
[⚙️ assert] elisp: "\n\n\n"
✅ got: #t
[⚙️ assert] elisp: "\n\n\n"
✅ got: #t
[⚙️ assert] elisp: "\n\n\n"
✅ got: #t
[⚙️ assert] elisp: "("
✅ got: #t
[⚙️ assert] elisp: "("
✅ got: #t
[⚙️ assert] elisp: "("
✅ got: #t
[⚙️ assert] elisp: ")"
✅ got: #t
[⚙️ assert] elisp: ")"
✅ got: #t
[⚙️ assert] elisp: ")"
✅ got: #t
[⚙️ assert] elisp: "())"
✅ got: #t
[⚙️ assert] elisp: "())"
✅ got: #t
[⚙️ assert] elisp: "())"
✅ got: #t
[⚙️ assert] elisp: "(defun)"
✅ got: #t
[⚙️ assert] elisp: "(defun)"
✅ got: #t
[⚙️ assert] elisp: "(defun)"
✅ got: #t
[⚙️ assert] elisp: "(defun defmacro)"
✅ got: #t
[⚙️ assert] elisp: "(defun defmacro)"
✅ got: #t
[⚙️ assert] elisp: "(defun defmacro)"
✅ got: #t
[⚙️ assert] elisp: "(defun f)"
✅ got: #t
[⚙️ assert] elisp: "(defun f)"
✅ got: #t
[⚙️ assert] elisp: "(defun f)"
✅ got: #t
[⚙️ assert] elisp: "(defun f ()"
✅ got: #t
[⚙️ assert] elisp: "(defun f ()"
✅ got: #t
[⚙️ assert] elisp: "(defun f ()"
✅ got: #t
[⚙️ assert] elisp: "(defmacro)"
✅ got: #t
[⚙️ assert] elisp: "(defmacro)"
✅ got: #t
[⚙️ assert] elisp: "(defmacro)"
✅ got: #t
[⚙️ assert] elisp: "(let)"
✅ got: #t
[⚙️ assert] elisp: "(let)"
✅ got: #t
[⚙️ assert] elisp: "(let)"
✅ got: #t
[⚙️ assert] elisp: "(let ())"
✅ got: #t
[⚙️ assert] elisp: "(let ())"
✅ got: #t
[⚙️ assert] elisp: "(let ())"
✅ got: #t
[⚙️ assert] elisp: "(case)"
✅ got: #t
[⚙️ assert] elisp: "(case)"
✅ got: #t
[⚙️ assert] elisp: "(case)"
✅ got: #t
[⚙️ assert] elisp: "(case x)"
✅ got: #t
[⚙️ assert] elisp: "(case x)"
✅ got: #t
[⚙️ assert] elisp: "(case x)"
✅ got: #t
[⚙️ assert] elisp: "(case x ())"
✅ got: #t
[⚙️ assert] elisp: "(case x ())"
✅ got: #t
[⚙️ assert] elisp: "(case x ())"
✅ got: #t
[⚙️ assert] elisp: "(case x ((cond) 1))"
✅ got: #t
[⚙️ assert] elisp: "(case x ((cond) 1))"
✅ got: #t
[⚙️ assert] elisp: "(case x ((cond) 1))"
✅ got: #t
[⚙️ assert] elisp: "(cond)"
✅ got: #t
[⚙️ assert] elisp: "(cond)"
✅ got: #t
[⚙️ assert] elisp: "(cond)"
✅ got: #t
[⚙️ assert] elisp: "(cond ())"
✅ got: #t
[⚙️ assert] elisp: "(cond ())"
✅ got: #t
[⚙️ assert] elisp: "(cond ())"
✅ got: #t
[⚙️ assert] elisp: "(lambda)"
✅ got: #t
[⚙️ assert] elisp: "(lambda)"
✅ got: #t
[⚙️ assert] elisp: "(lambda)"
✅ got: #t
[⚙️ assert] elisp: "(lambda ())"
✅ got: #t
[⚙️ assert] elisp: "(lambda ())"
✅ got: #t
[⚙️ assert] elisp: "(lambda ())"
✅ got: #t
[⚙️ assert] elisp: "(define)"
✅ got: #t
[⚙️ assert] elisp: "(define)"
✅ got: #t
[⚙️ assert] elisp: "(define)"
✅ got: #t
[⚙️ assert] elisp: "(define ())"
✅ got: #t
[⚙️ assert] elisp: "(define ())"
✅ got: #t
[⚙️ assert] elisp: "(define ())"
✅ got: #t
[⚙️ assert] elisp: "(quote)"
✅ got: #t
[⚙️ assert] elisp: "(quote)"
✅ got: #t
[⚙️ assert] elisp: "(quote)"
✅ got: #t
[⚙️ assert] elisp: "'"
✅ got: #t
[⚙️ assert] elisp: "'"
✅ got: #t
[⚙️ assert] elisp: "'"
✅ got: #t
[⚙️ assert] elisp: "#"
✅ got: #t
[⚙️ assert] elisp: "#"
✅ got: #t
[⚙️ assert] elisp: "#"
✅ got: #t
[⚙️ assert] elisp: "#;"
✅ got: #t
[⚙️ assert] elisp: "#;"
✅ got: #t
[⚙️ assert] elisp: "#;"
✅ got: #t
[⚙️ assert] elisp: "#|"
✅ got: #t
[⚙️ assert] elisp: "#|"
✅ got: #t
[⚙️ assert] elisp: "#|"
✅ got: #t
[⚙️ assert] elisp: "#\\"
✅ got: #t
[⚙️ assert] elisp: "#\\"
✅ got: #t
[⚙️ assert] elisp: "#\\"
✅ got: #t
[⚙️ assert] elisp: "?\\"
✅ got: #t
[⚙️ assert] elisp: "?\\"
✅ got: #t
[⚙️ assert] elisp: "?\\"
✅ got: #t
[⚙️ assert] elisp: "(a . )"
✅ got: #t
[⚙️ assert] elisp: "(a . )"
✅ got: #t
[⚙️ assert] elisp: "(a . )"
✅ got: #t
[⚙️ assert] elisp: "(a . b . c)"
✅ got: #t
[⚙️ assert] elisp: "(a . b . c)"
✅ got: #t
[⚙️ assert] elisp: "(a . b . c)"
✅ got: #t
[⚙️ assert] elisp: "(#)"
✅ got: #t
[⚙️ assert] elisp: "(#)"
✅ got: #t
[⚙️ assert] elisp: "(#)"
✅ got: #t
[⚙️ assert] elisp: "(list #;)"
✅ got: #t
[⚙️ assert] elisp: "(list #;)"
✅ got: #t
[⚙️ assert] elisp: "(list #;)"
✅ got: #t
[⚙️ assert] elisp: "(list #|x|#)"
✅ got: #t
[⚙️ assert] elisp: "(list #|x|#)"
✅ got: #t
[⚙️ assert] elisp: "(list #|x|#)"
✅ got: #t
[⚙️ assert] elisp: "(((("
✅ got: #t
[⚙️ assert] elisp: "(((("
✅ got: #t
[⚙️ assert] elisp: "(((("
✅ got: #t
[⚙️ assert] elisp: "))))"
✅ got: #t
[⚙️ assert] elisp: "))))"
✅ got: #t
[⚙️ assert] elisp: "))))"
✅ got: #t
[⚙️ assert] elisp: "(f :a 1 :a 2)"
✅ got: #t
[⚙️ assert] elisp: "(f :a 1 :a 2)"
✅ got: #t
[⚙️ assert] elisp: "(f :a 1 :a 2)"
✅ got: #t
[⚙️ assert] elisp: "(f \"unterminated"
✅ got: #t
[⚙️ assert] elisp: "(f \"unterminated"
✅ got: #t
[⚙️ assert] elisp: "(f \"unterminated"
✅ got: #t
[⚙️ assert] elisp: "(f #<garbage)"
✅ got: #t
[⚙️ assert] elisp: "(f #<garbage)"
✅ got: #t
[⚙️ assert] elisp: "(f #<garbage)"
✅ got: #t
[⚙️ assert] elisp: "(f #.(+ 1 2))"
✅ got: #t
[⚙️ assert] elisp: "(f #.(+ 1 2))"
✅ got: #t
[⚙️ assert] elisp: "(f #.(+ 1 2))"
✅ got: #t
[⚙️ assert] elisp: "(let ((x 1) (x 2)) x)"
✅ got: #t
[⚙️ assert] elisp: "(let ((x 1) (x 2)) x)"
✅ got: #t
[⚙️ assert] elisp: "(let ((x 1) (x 2)) x)"
✅ got: #t
[⚙️ assert] elisp: "(when)"
✅ got: #t
[⚙️ assert] elisp: "(when)"
✅ got: #t
[⚙️ assert] elisp: "(when)"
✅ got: #t
[⚙️ assert] elisp: "(unless)"
✅ got: #t
[⚙️ assert] elisp: "(unless)"
✅ got: #t
[⚙️ assert] elisp: "(unless)"
✅ got: #t
[⚙️ assert] elisp: "(if)"
✅ got: #t
[⚙️ assert] elisp: "(if)"
✅ got: #t
[⚙️ assert] elisp: "(if)"
✅ got: #t
[⚙️ assert] elisp: "(do)"
✅ got: #t
[⚙️ assert] elisp: "(do)"
✅ got: #t
[⚙️ assert] elisp: "(do)"
✅ got: #t
[⚙️ assert] elisp: "(λ (x) x)"
✅ got: #t
[⚙️ assert] elisp: "(λ (x) x)"
✅ got: #t
[⚙️ assert] elisp: "(λ (x) x)"
✅ got: #t
[⚙️ assert] cl: ""
✅ got: #t
[⚙️ assert] cl: ""
✅ got: #t
[⚙️ assert] cl: ""
✅ got: #t
[⚙️ assert] cl: " "
✅ got: #t
[⚙️ assert] cl: " "
✅ got: #t
[⚙️ assert] cl: " "
✅ got: #t
[⚙️ assert] cl: "\n\n\n"
✅ got: #t
[⚙️ assert] cl: "\n\n\n"
✅ got: #t
[⚙️ assert] cl: "\n\n\n"
✅ got: #t
[⚙️ assert] cl: "("
✅ got: #t
[⚙️ assert] cl: "("
✅ got: #t
[⚙️ assert] cl: "("
✅ got: #t
[⚙️ assert] cl: ")"
✅ got: #t
[⚙️ assert] cl: ")"
✅ got: #t
[⚙️ assert] cl: ")"
✅ got: #t
[⚙️ assert] cl: "())"
✅ got: #t
[⚙️ assert] cl: "())"
✅ got: #t
[⚙️ assert] cl: "())"
✅ got: #t
[⚙️ assert] cl: "(defun)"
✅ got: #t
[⚙️ assert] cl: "(defun)"
✅ got: #t
[⚙️ assert] cl: "(defun)"
✅ got: #t
[⚙️ assert] cl: "(defun defmacro)"
✅ got: #t
[⚙️ assert] cl: "(defun defmacro)"
✅ got: #t
[⚙️ assert] cl: "(defun defmacro)"
✅ got: #t
[⚙️ assert] cl: "(defun f)"
✅ got: #t
[⚙️ assert] cl: "(defun f)"
✅ got: #t
[⚙️ assert] cl: "(defun f)"
✅ got: #t
[⚙️ assert] cl: "(defun f ()"
✅ got: #t
[⚙️ assert] cl: "(defun f ()"
✅ got: #t
[⚙️ assert] cl: "(defun f ()"
✅ got: #t
[⚙️ assert] cl: "(defmacro)"
✅ got: #t
[⚙️ assert] cl: "(defmacro)"
✅ got: #t
[⚙️ assert] cl: "(defmacro)"
✅ got: #t
[⚙️ assert] cl: "(let)"
✅ got: #t
[⚙️ assert] cl: "(let)"
✅ got: #t
[⚙️ assert] cl: "(let)"
✅ got: #t
[⚙️ assert] cl: "(let ())"
✅ got: #t
[⚙️ assert] cl: "(let ())"
✅ got: #t
[⚙️ assert] cl: "(let ())"
✅ got: #t
[⚙️ assert] cl: "(case)"
✅ got: #t
[⚙️ assert] cl: "(case)"
✅ got: #t
[⚙️ assert] cl: "(case)"
✅ got: #t
[⚙️ assert] cl: "(case x)"
✅ got: #t
[⚙️ assert] cl: "(case x)"
✅ got: #t
[⚙️ assert] cl: "(case x)"
✅ got: #t
[⚙️ assert] cl: "(case x ())"
✅ got: #t
[⚙️ assert] cl: "(case x ())"
✅ got: #t
[⚙️ assert] cl: "(case x ())"
✅ got: #t
[⚙️ assert] cl: "(case x ((cond) 1))"
✅ got: #t
[⚙️ assert] cl: "(case x ((cond) 1))"
✅ got: #t
[⚙️ assert] cl: "(case x ((cond) 1))"
✅ got: #t
[⚙️ assert] cl: "(cond)"
✅ got: #t
[⚙️ assert] cl: "(cond)"
✅ got: #t
[⚙️ assert] cl: "(cond)"
✅ got: #t
[⚙️ assert] cl: "(cond ())"
✅ got: #t
[⚙️ assert] cl: "(cond ())"
✅ got: #t
[⚙️ assert] cl: "(cond ())"
✅ got: #t
[⚙️ assert] cl: "(lambda)"
✅ got: #t
[⚙️ assert] cl: "(lambda)"
✅ got: #t
[⚙️ assert] cl: "(lambda)"
✅ got: #t
[⚙️ assert] cl: "(lambda ())"
✅ got: #t
[⚙️ assert] cl: "(lambda ())"
✅ got: #t
[⚙️ assert] cl: "(lambda ())"
✅ got: #t
[⚙️ assert] cl: "(define)"
✅ got: #t
[⚙️ assert] cl: "(define)"
✅ got: #t
[⚙️ assert] cl: "(define)"
✅ got: #t
[⚙️ assert] cl: "(define ())"
✅ got: #t
[⚙️ assert] cl: "(define ())"
✅ got: #t
[⚙️ assert] cl: "(define ())"
✅ got: #t
[⚙️ assert] cl: "(quote)"
✅ got: #t
[⚙️ assert] cl: "(quote)"
✅ got: #t
[⚙️ assert] cl: "(quote)"
✅ got: #t
[⚙️ assert] cl: "'"
✅ got: #t
[⚙️ assert] cl: "'"
✅ got: #t
[⚙️ assert] cl: "'"
✅ got: #t
[⚙️ assert] cl: "#"
✅ got: #t
[⚙️ assert] cl: "#"
✅ got: #t
[⚙️ assert] cl: "#"
✅ got: #t
[⚙️ assert] cl: "#;"
✅ got: #t
[⚙️ assert] cl: "#;"
✅ got: #t
[⚙️ assert] cl: "#;"
✅ got: #t
[⚙️ assert] cl: "#|"
✅ got: #t
[⚙️ assert] cl: "#|"
✅ got: #t
[⚙️ assert] cl: "#|"
✅ got: #t
[⚙️ assert] cl: "#\\"
✅ got: #t
[⚙️ assert] cl: "#\\"
✅ got: #t
[⚙️ assert] cl: "#\\"
✅ got: #t
[⚙️ assert] cl: "?\\"
✅ got: #t
[⚙️ assert] cl: "?\\"
✅ got: #t
[⚙️ assert] cl: "?\\"
✅ got: #t
[⚙️ assert] cl: "(a . )"
✅ got: #t
[⚙️ assert] cl: "(a . )"
✅ got: #t
[⚙️ assert] cl: "(a . )"
✅ got: #t
[⚙️ assert] cl: "(a . b . c)"
✅ got: #t
[⚙️ assert] cl: "(a . b . c)"
✅ got: #t
[⚙️ assert] cl: "(a . b . c)"
✅ got: #t
[⚙️ assert] cl: "(#)"
✅ got: #t
[⚙️ assert] cl: "(#)"
✅ got: #t
[⚙️ assert] cl: "(#)"
✅ got: #t
[⚙️ assert] cl: "(list #;)"
✅ got: #t
[⚙️ assert] cl: "(list #;)"
✅ got: #t
[⚙️ assert] cl: "(list #;)"
✅ got: #t
[⚙️ assert] cl: "(list #|x|#)"
✅ got: #t
[⚙️ assert] cl: "(list #|x|#)"
✅ got: #t
[⚙️ assert] cl: "(list #|x|#)"
✅ got: #t
[⚙️ assert] cl: "(((("
✅ got: #t
[⚙️ assert] cl: "(((("
✅ got: #t
[⚙️ assert] cl: "(((("
✅ got: #t
[⚙️ assert] cl: "))))"
✅ got: #t
[⚙️ assert] cl: "))))"
✅ got: #t
[⚙️ assert] cl: "))))"
✅ got: #t
[⚙️ assert] cl: "(f :a 1 :a 2)"
✅ got: #t
[⚙️ assert] cl: "(f :a 1 :a 2)"
✅ got: #t
[⚙️ assert] cl: "(f :a 1 :a 2)"
✅ got: #t
[⚙️ assert] cl: "(f \"unterminated"
✅ got: #t
[⚙️ assert] cl: "(f \"unterminated"
✅ got: #t
[⚙️ assert] cl: "(f \"unterminated"
✅ got: #t
[⚙️ assert] cl: "(f #<garbage)"
✅ got: #t
[⚙️ assert] cl: "(f #<garbage)"
✅ got: #t
[⚙️ assert] cl: "(f #<garbage)"
✅ got: #t
[⚙️ assert] cl: "(f #.(+ 1 2))"
✅ got: #t
[⚙️ assert] cl: "(f #.(+ 1 2))"
✅ got: #t
[⚙️ assert] cl: "(f #.(+ 1 2))"
✅ got: #t
[⚙️ assert] cl: "(let ((x 1) (x 2)) x)"
✅ got: #t
[⚙️ assert] cl: "(let ((x 1) (x 2)) x)"
✅ got: #t
[⚙️ assert] cl: "(let ((x 1) (x 2)) x)"
✅ got: #t
[⚙️ assert] cl: "(when)"
✅ got: #t
[⚙️ assert] cl: "(when)"
✅ got: #t
[⚙️ assert] cl: "(when)"
✅ got: #t
[⚙️ assert] cl: "(unless)"
✅ got: #t
[⚙️ assert] cl: "(unless)"
✅ got: #t
[⚙️ assert] cl: "(unless)"
✅ got: #t
[⚙️ assert] cl: "(if)"
✅ got: #t
[⚙️ assert] cl: "(if)"
✅ got: #t
[⚙️ assert] cl: "(if)"
✅ got: #t
[⚙️ assert] cl: "(do)"
✅ got: #t
[⚙️ assert] cl: "(do)"
✅ got: #t
[⚙️ assert] cl: "(do)"
✅ got: #t
[⚙️ assert] cl: "(λ (x) x)"
✅ got: #t
[⚙️ assert] cl: "(λ (x) x)"
✅ got: #t
[⚙️ assert] cl: "(λ (x) x)"
✅ got: #t
+----------------------------------------------+
[📑 suite] the browser facade
[🧪 test] the version is sift's version
✅ got: 1.21.0
[🧪 test] checkers selects the rules to run
[⚙️ assert] only the rule that was asked for
✅ got: 1
[⚙️ assert] which is the one
✅ got: if-without-else
[🧪 test] a hover describes the symbol under the cursor
[⚙️ assert] there is an answer
✅ got: #t
[⚙️ assert] with contents the editor can draw
✅ got: #t
[🧪 test] the counts add up
[⚙️ assert] one error for the unterminated form
✅ got: 1
[⚙️ assert] no warnings
✅ got: 0
[🧪 test] a definition in the buffer is found
[⚙️ assert] the one definition there is
✅ got: 1
[⚙️ assert] on the line it is written on
✅ got: 0
[🧪 test] the browser's SRFI-13 answers what Guile's does
[⚙️ assert] the stand-in loads and answers
✅ got: 0
[⚙️ assert] the format answer is the same over the stand-in
✅ got: {"ok":true,"result":{"source":";; sift:disable-next-line if-without-else\n(define (square x)\n (* x x))\n","changed":true,"warnings":[]}}
[⚙️ assert] the stand-in loads and answers
✅ got: 0
[⚙️ assert] the lint answer is the same over the stand-in
✅ got: {"ok":true,"result":{"warnings":[{"rule":"if-without-else","code":"SIFT012","severity":"warning","message":"`if` has no else branch; `when` says it once","line":2,"column":4,"offset":15,"from":15,"to":17,"fixable":true}],"counts":{"error":0,"warning":1,"info":0},"severity":"info"}}
[⚙️ assert] the stand-in loads and answers
✅ got: 0
[⚙️ assert] the fix answer is the same over the stand-in
✅ got: {"ok":true,"result":{"source":"(define (f) 1)\n","applied":1,"changed":true,"warnings":[]}}
[🧪 test] completion offers the names the buffer defines
[⚙️ assert] the name that starts with what is typed
✅ got: square
[🧪 test] an unknown dialect is a usage error
[⚙️ assert] unknown dialect: it is refused
✅ got: false
[⚙️ assert] unknown dialect: as a usage error
✅ got: usage
[⚙️ assert] unknown dialect: with a sentence to read
✅ got: #t
[🧪 test] a hover where there is nothing to say answers null
[⚙️ assert] no hover, and no error either
✅ got: null
[🧪 test] every Guile library the browser build imports has a stand-in
[⚙️ assert] web/compat covers what the closure imports and the target lacks
✅ got: ()
[🧪 test] the facade imports five core modules, and no more
[⚙️ assert] the browser build's dependency on the core is this list
✅ got: ((sift analysis) (sift format) (sift json) (sift lint) (sift records))
[🧪 test] a request with no op is a usage error
[⚙️ assert] no op: it is refused
✅ got: false
[⚙️ assert] no op: as a usage error
✅ got: usage
[⚙️ assert] no op: with a sentence to read
✅ got: #t
[🧪 test] inlay hints name the arguments a call passes
[⚙️ assert] one per positional argument
✅ got: 2
[⚙️ assert] named by the formal list, with room after the name
✅ got: width
[🧪 test] lint answers one finding with its rule, code and place
[⚙️ assert] one finding
✅ got: 1
[⚙️ assert] named
✅ got: if-without-else
[⚙️ assert] coded
✅ got: SIFT012
[⚙️ assert] with a severity
✅ got: warning
[⚙️ assert] on line 2
✅ got: 2
[⚙️ assert] at column 4
✅ got: 4
[⚙️ assert] with a range to underline
✅ got: #t
[⚙️ assert] and the news that it can be fixed
✅ got: true
[🧪 test] fix on a formatted buffer changes nothing
[⚙️ assert] nothing to do
✅ got: false
[🧪 test] the outline names what the buffer defines
[⚙️ assert] one top-level form
✅ got: 1
[⚙️ assert] named after the definition
✅ got: square
[⚙️ assert] with a range to draw it at
✅ got: #t
[🧪 test] the highlights tell a declaration from a use
[⚙️ assert] the declaration and the call
✅ got: 2
[⚙️ assert] marked apart
✅ got: #t
[🧪 test] the rules are listed with their codes and dialects
[⚙️ assert] all of them
✅ got: 92
[⚙️ assert] and the one we asked about is there
✅ got: #t
[⚙️ assert] with its code
✅ got: SIFT012
[⚙️ assert] its dialect
✅ got: scheme
[⚙️ assert] and an example to read
✅ got: #t
[🧪 test] the page names no path from the root of the site
[⚙️ assert] every URL is relative, so the editor works in a subdirectory
✅ got: ()
[🧪 test] the browser's SRFI-13 is the stand-in web/compat carries
[⚙️ assert] web/compat/srfi/srfi-13.scm is what a browser build finds
✅ got: #t
[🧪 test] the editor asks for the wasm beside itself
[⚙️ assert] the module's own URL is where sift.wasm is found
✅ got: #t
[⚙️ assert] and not a path from wherever the page happens to be served
✅ got: #f
[🧪 test] the dialect reaches the formatter
[⚙️ assert] Emacs Lisp keeps its parentheses
✅ got: (cond ((= x 1) (a)))
[⚙️ assert] Scheme writes its clauses with brackets
✅ got: (cond [(= x 1) (a)])
[🧪 test] a format of a broken file answers the error rather than throwing
[⚙️ assert] the reader's finding is in the answer
✅ got: 1
[⚙️ assert] at error severity
✅ got: error
[🧪 test] a project macro can be given its indentation
[⚙️ assert] the rule from the request reached the formatter
✅ got: (with-thing
(a)
(b))
[🧪 test] an unknown op is a usage error
[⚙️ assert] unknown op: it is refused
✅ got: false
[⚙️ assert] unknown op: as a usage error
✅ got: usage
[⚙️ assert] unknown op: with a sentence to read
✅ got: #t
[🧪 test] format says whether it changed anything
[⚙️ assert] a formatted buffer is not changed
✅ got: false
[⚙️ assert] an unformatted buffer is
✅ got: true
[🧪 test] a rule that applies to every dialect lists the three
[⚙️ assert] symbol `all' is spelled out
✅ got: 3
[🧪 test] the answer is JSON, and reads back
[⚙️ assert] a string comes back
✅ got: #t
[⚙️ assert] and it is a document sift can read again
✅ got: #t
[🧪 test] a source that is not a string is a usage error
[⚙️ assert] a number for a source: it is refused
✅ got: false
[⚙️ assert] a number for a source: as a usage error
✅ got: usage
[⚙️ assert] a number for a source: with a sentence to read
✅ got: #t
[🧪 test] every URL the page names carries the build stamp
[⚙️ assert] the page names something
✅ got: #t
[⚙️ assert] a URL that does not change is a deploy a cache hides
✅ got: ()
[🧪 test] format answers the formatted text
[⚙️ assert] the indentation is the formatter's
✅ got: (define (square x)
(* x x))
[🧪 test] severity filters what is reported
[⚙️ assert] an info finding is below an error threshold
✅ got: 0
[🧪 test] a request that is not JSON is an error, not an exception
[⚙️ assert] it is refused
✅ got: false
[⚙️ assert] as a request error
✅ got: request
[🧪 test] the suppression comments a file carries are honoured;;; note: source file ./tests/lsp.scm
;;; newer than compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/tests/lsp.scm.go
;;; compiling ./tests/lsp.scm
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/tests/lsp.scm.go
loading tests/pool.scm
loading tests/reader-cl.scm
loading tests/reader-elisp.scm
loading tests/reader-scheme.scm
loading tests/robustness.scm
loading tests/web.scm
;;; note: source file ./src/sift/analysis.scm
;;; newer than compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/analysis.scm.go
;;; compiling ./src/sift/analysis.scm
;;; compiled /root/.cache/guile/ccache/3.0-LE-8-4.7/etc/byggsteg/job-clone/sift/trunk/src/sift/analysis.scm.go
[⚙️ assert] a disabled rule says nothing
✅ got: #f
[⚙️ assert] and the rules around it still speak
✅ got: #t
[🧪 test] the style reaches the formatter
[⚙️ assert] dangling closers are their own line
✅ got: (define (f)
(a)
)
[🧪 test] fix applies the fixes and says how many
[⚙️ assert] the let with one binding folded away
✅ got: (define (f) 1)
[⚙️ assert] and it says how many fixes it made
✅ got: #t
[⚙️ assert] and that the buffer changed
✅ got: true
[🧪 test] a question without an offset is a usage error
[⚙️ assert] hover with no offset: it is refused
✅ got: false
[⚙️ assert] hover with no offset: as a usage error
✅ got: usage
[⚙️ assert] hover with no offset: with a sentence to read
✅ got: #t
[🧪 test] the core does not know the browser exists
[⚙️ assert] no file under src/sift/ names the browser, Wasm or Hoot
✅ got: ()
ℹ️ info - ran 102 tasks in: 36 seconds, 8391 microseconds
--------------------------------------------------------------
Maak 0.14.0: the infinitely extensible command runner
Loading tasks from Maak file: /etc/byggsteg/job-clone/sift/trunk/maak.scm
Executing Maak tasks: test
--------------------------------------------------------------
=> Running Maak task: test
Run the whole Veritas suite.
Veritas is the only test framework this project uses; it is loaded from
VERITAS_DIR (~/Hacking/veritas by default) so that the checkout under test is
the checkout that is being developed, and the load path is passed here rather
than exported by the caller, so `maak test' works from a clean checkout.
Execute command:
guix time-machine --channels=channels.scm -- shell -m manifest.scm -- guile -L ./src -L . -L ./web -c '(begin (use-modules (tests run)) (exit (run-all!)))'
Executing: guix time-machine --channels=channels.scm -- shell -m manifest.scm -- guile -L ./src -L . -L ./web -c '(begin (use-modules (tests run)) (exit (run-all!)))'
→ running command: cd /etc/byggsteg/job-clone/sift/trunk && maak emacs-test
channels.scm:17:6: warning: channel 'jointhefreeworld' is not trusted
Running 31 tests (2026-11-03 10:46:17+0100, selector ‘t’)
passed 1/31 sift-test-check-buffer (0.027492 sec)
passed 2/31 sift-test-ci-command (0.000105 sec)
passed 3/31 sift-test-code-actions-need-a-server (0.000046 sec)
passed 4/31 sift-test-diagnostics-empty (0.000032 sec)
passed 5/31 sift-test-diagnostics-shape (0.000122 sec)
passed 6/31 sift-test-dialect-from-major-mode (0.000050 sec)
passed 7/31 sift-test-eglot-contact-runs-the-server (0.000043 sec)
passed 8/31 sift-test-eglot-contact-says-when-sift-is-missing (0.000068 sec)
passed 9/31 sift-test-eglot-leaves-formatting-to-the-server (0.126021 sec)
passed 10/31 sift-test-eglot-setup-leaves-the-flymake-backend-alone (0.000047 sec)
passed 11/31 sift-test-eglot-setup-registers-the-modes (0.000052 sec)
passed 12/31 sift-test-eglot-silences-the-flymake-backend (0.000024 sec)
passed 13/31 sift-test-error-regexp (0.000039 sec)
sift: this buffer would be reformatted (M-x sift-format-buffer)
passed 14/31 sift-test-explain (0.112620 sec)
sift: fixed
passed 15/31 sift-test-fix-buffer (0.058869 sec)
passed 16/31 sift-test-fix-buffer-refuses-a-parse-error (0.071377 sec)
passed 17/31 sift-test-fix-string-filters-by-checker (0.092075 sec)
passed 18/31 sift-test-flymake-backend (0.136228 sec)
passed 19/31 sift-test-flymake-backend-reports-a-parse-error (0.140554 sec)
passed 20/31 sift-test-flymake-backend-unknown-mode (0.000087 sec)
passed 21/31 sift-test-flymake-cancels-the-run-it-replaces (0.000886 sec)
passed 22/31 sift-test-format-broken-source-says-why (0.069615 sec)
sift: formatted
passed 23/31 sift-test-format-buffer (0.088463 sec)
sift: formatted
sift: already formatted
passed 24/31 sift-test-format-buffer-is-idempotent (0.076224 sec)
passed 25/31 sift-test-format-buffer-refuses-a-parse-error (0.034060 sec)
sift: formatted
passed 26/31 sift-test-format-elisp (0.033234 sec)
sift: formatted the region
passed 27/31 sift-test-format-region (0.036001 sec)
passed 28/31 sift-test-rule-at-point-from-compilation-line (0.000073 sec)
passed 29/31 sift-test-rule-names (0.037633 sec)
passed 30/31 sift-test-severity-is-said-only-when-it-is-set (0.000039 sec)
passed 31/31 sift-test-version (0.032954 sec)
Ran 31 tests, 31 results as expected, 0 unexpected (2026-11-03 10:46:18+0100, 1.182782 sec)
--------------------------------------------------------------
Maak 0.14.0: the infinitely extensible command runner
Loading tasks from Maak file: /etc/byggsteg/job-clone/sift/trunk/maak.scm
Executing Maak tasks: emacs-test
--------------------------------------------------------------
=> Running Maak task: emacs-test
Run the Emacs package's ERT suite.
ERT is the test framework Emacs ships, and it is the right one here: the
package is a thin wrapper around the executable, so the tests run the
executable and read what came back, the way a user would. The Guile suite is
Veritas; this one never runs the two together.
Execute command:
guix time-machine --channels=channels.scm -- shell -m manifest.scm -- emacs -Q --batch -L emacs -l ert -l emacs/sift-test.el -f ert-run-tests-batch-and-exit
Executing: guix time-machine --channels=channels.scm -- shell -m manifest.scm -- emacs -Q --batch -L emacs -l ert -l emacs/sift-test.el -f ert-run-tests-batch-and-exit
→ running command: cd /etc/byggsteg/job-clone/sift/trunk && maak web-deploy
--------------------------------------------------------------
Maak 0.14.0: the infinitely extensible command runner
Loading tasks from Maak file: /etc/byggsteg/job-clone/sift/trunk/maak.scm
Executing Maak tasks: web-deploy
--------------------------------------------------------------
=> Running Maak task: web-deploy
Build the browser build and publish it to the web directory.
Deployment is a copy, the way the rest of jointhefreeworld.org is deployed: the
directory is emptied and the fresh build is put in its place, so a file this
build does not have does not linger on the server beside the one that replaced
it. It runs where that directory is -- on the machine that serves, or in the CI
job that runs there -- and that is all it needs: no ssh, no rsync, and no server
to reload, because a file that is there is a file that is served.
The build is removed afterwards the way `maak deploy' removes the documentation
it published: what the tree keeps is the source, and a build directory left
behind is a build directory the next deploy might copy.
Execute command:
sh web/build.sh
sift: the Hoot on PATH cannot compile; asking Guix for guile-next guile-hoot
sift: (this is the first build on a machine; it takes a while and only once)
sift: using guile (GNU Guile) 3.0.11-1.b0f6549 from PATH
sift: compiling web/main.scm -> /etc/byggsteg/job-clone/sift/trunk/web/dist/sift.wasm
wrote `/etc/byggsteg/job-clone/sift/trunk/web/dist/sift.wasm'
WARNING: (% %library-group117 sift records): `format' imported from both (% %library-group117 ice-9 format) and (% %library-group117 guile)
WARNING: (% %library-group117 sift json): `format' imported from both (% %library-group117 ice-9 format) and (% %library-group117 guile)
WARNING: (% %library-group117 sift reader): `format' imported from both (% %library-group117 ice-9 format) and (% %library-group117 guile)
WARNING: (% %library-group117 sift checkers whitespace): `format' imported from both (% %library-group117 ice-9 format) and (% %library-group117 guile)
WARNING: (% %library-group117 sift checkers parens): `format' imported from both (% %library-group117 ice-9 format) and (% %library-group117 guile)
WARNING: (% %library-group117 sift checkers bodies): `format' imported from both (% %library-group117 ice-9 format) and (% %library-group117 guile)
WARNING: (% %library-group117 sift checkers scheme): `format' imported from both (% %library-group117 ice-9 format) and (% %library-group117 guile)
WARNING: (% %library-group117 sift checkers elisp): `format' imported from both (% %library-group117 ice-9 format) and (% %library-group117 guile)
WARNING: (% %library-group117 sift checkers cl): `format' imported from both (% %library-group117 ice-9 format) and (% %library-group117 guile)
WARNING: (% %library-group117 sift checkers ergonomics): `format' imported from both (% %library-group117 ice-9 format) and (% %library-group117 guile)
WARNING: (% %library-group117 sift checkers naming): `format' imported from both (% %library-group117 ice-9 format) and (% %library-group117 guile)
WARNING: (% %library-group117 sift checkers simplify): `format' imported from both (% %library-group117 ice-9 format) and (% %library-group117 guile)
WARNING: (% %library-group117 sift checkers practices): `format' imported from both (% %library-group117 ice-9 format) and (% %library-group117 guile)
WARNING: (% %library-group117 sift checkers guix): `format' imported from both (% %library-group117 ice-9 format) and (% %library-group117 guile)
WARNING: (% %library-group117 sift checkers inference): `format' imported from both (% %library-group117 ice-9 format) and (% %library-group117 guile)
WARNING: (% %library-group117 sift lint): `format' imported from both (% %library-group117 ice-9 format) and (% %library-group117 guile)
WARNING: (% %library-group117 sift analysis): `format' imported from both (% %library-group117 ice-9 format) and (% %library-group117 guile)
WARNING: (% %library-group117 sift web): `format' imported from both (% %library-group117 ice-9 format) and (% %library-group117 guile)
sift: /etc/byggsteg/job-clone/sift/trunk/web/dist is ready
sift: build 1.21.0-b8802ca-20261103T094621Z
sift: index.html 8.0K
sift: editor.js 24K
sift: editor.css 8.0K
sift: favicon.png 24K
sift: sift.wasm 3.2M
sift: reflect.js 56K
sift: reflect.wasm 8.0K
sift: wtf8.wasm 4.0K
sift: serve it: cd /etc/byggsteg/job-clone/sift/trunk/web/dist && python3 -m http.server 8080
publishing web/dist to /srv/http/jointhefreeworld.org/siftremoved '/srv/http/jointhefreeworld.org/sift/sift.wasm'
removed '/srv/http/jointhefreeworld.org/sift/reflect.js'
removed '/srv/http/jointhefreeworld.org/sift/reflect.wasm'
removed '/srv/http/jointhefreeworld.org/sift/wtf8.wasm'
removed '/srv/http/jointhefreeworld.org/sift/index.html'
removed '/srv/http/jointhefreeworld.org/sift/editor.js'
removed '/srv/http/jointhefreeworld.org/sift/editor.css'
removed '/srv/http/jointhefreeworld.org/sift/favicon.png'
removed directory '/srv/http/jointhefreeworld.org/sift'
'web/dist' -> '/srv/http/jointhefreeworld.org/sift'
'web/dist/sift.wasm' -> '/srv/http/jointhefreeworld.org/sift/sift.wasm'
'web/dist/reflect.js' -> '/srv/http/jointhefreeworld.org/sift/reflect.js'
'web/dist/reflect.wasm' -> '/srv/http/jointhefreeworld.org/sift/reflect.wasm'
'web/dist/wtf8.wasm' -> '/srv/http/jointhefreeworld.org/sift/wtf8.wasm'
'web/dist/index.html' -> '/srv/http/jointhefreeworld.org/sift/index.html'
'web/dist/editor.js' -> '/srv/http/jointhefreeworld.org/sift/editor.js'
'web/dist/editor.css' -> '/srv/http/jointhefreeworld.org/sift/editor.css'
'web/dist/favicon.png' -> '/srv/http/jointhefreeworld.org/sift/favicon.png'
removed 'web/dist/sift.wasm'
removed 'web/dist/reflect.js'
removed 'web/dist/reflect.wasm'
removed 'web/dist/wtf8.wasm'
removed 'web/dist/index.html'
removed 'web/dist/editor.js'
removed 'web/dist/editor.css'
removed 'web/dist/favicon.png'
removed directory 'web/dist'