; -*- mode: emacs-lisp; lexical-binding: t -*-

(eldev-require-version "1.11.2")

(setf eldev-project-source-dirs '("lisp/"))
(setf eldev-project-main-file "cider.el")

(eldev-use-package-archive 'gnu)

;; For compatibility; e.g. with MELPA Stable one test fails.
(eldev-use-package-archive 'melpa-unstable)

(eldev-use-plugin 'autoloads)

(eldev-add-loading-roots 'test "test/utils")
(eldev-add-extra-dependencies 'runtime '(:package logview :optional t))
(eldev-add-extra-dependencies 'runtime '(:package clojure-ts-mode :optional t))

;; slightly increase the maximum (applies to checkdoc and the byte compiler alike)
(setq byte-compile-docstring-max-column 100)

;; allow commas to indicate that the first sentence continues, which enables longer first sentences
(setq checkdoc-permit-comma-termination-flag t)

;; the experimental third-person-verb check misfires on nouns like "tests"
;; and "highlights", which a Clojure IDE can hardly avoid in docstrings
(setq checkdoc-verb-check-experimental-flag nil)

(defvar cider-test-type 'main)
(setf eldev-standard-excludes `(:or ,eldev-standard-excludes
                                    ;; Exclude flycheck temporary files
                                    "./flycheck_*.el"
                                    ;; Avoid including files in test "projects".
                                    (eldev-pcase-exhaustive cider-test-type
                                                            (`main            "./test/*/")
                                                            (`integration     '("./test/"   "!./test/integration"))
                                                            (`clojure-ts-mode '("./test/*/" "!./test/clojure-ts-mode"))
                                                            (`all             '("./test/*/" "!./test/integration")))
                                    "test/integration/projects"
                                    ;; This file is _supposed_ to be excluded
                                    ;; from automated testing.
                                    "test/cider-tests--no-auto.el"))

(eldev-defoption cider-test-selection (type)
  "Select tests to run; type can be `main', `integration', `clojure-ts-mode' or `all'"
  :options        (-T --test-type)
  :for-command    test
  :value          TYPE
  :default-value  cider-test-type
  (unless (memq (intern type) '(main integration clojure-ts-mode all))
    (signal 'eldev-wrong-option-usage `("unknown test type `%s'" ,type)))
  (setf cider-test-type (intern type)))

;; The main suite sets up its buffers with `clojure-mode'.  This option
;; reroutes every such call to `clojure-ts-mode', so the whole suite (not
;; just the handful of specs under test/clojure-ts-mode/) exercises the
;; tree-sitter code paths.
(defvar cider-test-under-clojure-ts-mode nil)
(eldev-defoption cider-test-under-clojure-ts-mode ()
  "Run the specs with `clojure-mode' buffers switched to `clojure-ts-mode'"
  :options        (--under-clojure-ts-mode)
  :for-command    test
  (setf cider-test-under-clojure-ts-mode t))

(add-hook 'eldev-load-dependencies-hook
          (lambda (type additional-sets)
            (when (and (or (eq cider-test-type 'clojure-ts-mode)
                           cider-test-under-clojure-ts-mode)
                       (member 'runtime additional-sets))
              (message "Installing tree-sitter grammars")
              ;; An already-installed optional dependency isn't activated
              ;; this early in the run (a fresh install is), so activate it
              ;; explicitly before requiring it.
              (package-activate 'clojure-ts-mode)
              (require 'clojure-ts-mode)
              (clojure-ts--ensure-grammars)
              (when cider-test-under-clojure-ts-mode
                (message "Routing `clojure-mode' to `clojure-ts-mode' for this run")
                (advice-add 'clojure-mode :override
                            (lambda (&rest _) (clojure-ts-mode)))))))

(add-hook 'eldev-test-hook
          (lambda ()
            (eldev-verbose "Using cider tests of type `%s'" cider-test-type)))
(add-hook 'eldev-executing-command-hook
          (lambda (command)
            (unless (eq command 'test)
              ;; So that e.g. byte-compilation works on all tests.
              (setf cider-test-type 'all))))

;; CIDER cannot be compiled otherwise.
(setf eldev-build-load-before-byte-compiling t)

;; Emacs 31 stamps source positions onto compiler-macro expansions in place
;; (`macroexp--posify-form'), which corrupts the stored inline body of any
;; argument-less `cl-defsubst' - `queue-create' is the one that bites us -
;; once something calling it has been byte-compiled in this process.  In
;; packaged mode Eldev compiles CIDER right before loading the specs, so the
;; first test run after a source change failed 9 specs with
;; `invalid-function cl-block' (Emacs bug#79599).  Upstream added this switch
;; for exactly that kind of trouble; the only cost is less precise positions
;; in byte-compile warnings.
(setq macroexp-enable-preserve-posification nil)

;; On macOS bsdtar stores extended attributes as `._*' AppleDouble entries,
;; and Eldev's packaged copy of the project would then get a hundred of them
;; byte-compiled as Lisp.
(setenv "COPYFILE_DISABLE" "1")

;; package-lint is disabled because nrepl-*.el files intentionally use
;; the `nrepl-' prefix instead of the `cider-' package prefix.
;; `doc' is the linter's canonical name; `checkdoc' is only a command-line
;; alias, and the default-linter matching doesn't resolve aliases - with
;; `(checkdoc)' here, a bare `eldev lint' (which is what CI runs) silently
;; lints nothing.
(setf eldev-lint-default '(doc))

;; Coverage reports via undercover.  Off unless asked for, so this changes
;; nothing for regular runs and CI; the flags given to `-u' take precedence.
;; Use `eldev test -u on,text' for a summary or
;; `eldev test -u on,simplecov -U coverage.json' for a per-line report.
;; Don't combine with `-p': the instrumentation needs the sources as-is.
(eldev-use-plugin 'undercover)
(setf eldev-undercover-config '(off))
