;;; check-test-autoloads --- Reject generated autoload dependencies -*- lexical-binding: t; -*-

(defconst jabber-check-test-autoloads--operations '(load load-file require))

(defun jabber-check-test-autoloads--target-p (value)
  "Return non-nil when VALUE names the generated Jabber autoload file."
  (cond
   ((symbolp value) (string= (symbol-name value) "jabber-autoloads"))
   ((stringp value)
    (string-match-p
     "\\(?:\\`\\|/\\)jabber-autoloads\\(?:\\.el[cn]?\\)?\\'" value))
   ((consp value)
    (or (jabber-check-test-autoloads--target-p (car value))
        (jabber-check-test-autoloads--target-p (cdr value))))))

(defun jabber-check-test-autoloads--dependency-p (form)
  "Return non-nil when FORM directly loads generated Jabber autoloads."
  (and
   (consp form)
   (not (eq (car form) 'quote))
   (or (and (memq (car form) jabber-check-test-autoloads--operations)
            (or (jabber-check-test-autoloads--target-p (cadr form))
                (and (eq (car form) 'require)
                     (jabber-check-test-autoloads--target-p (caddr form)))))
       (jabber-check-test-autoloads--dependency-p (car form))
       (jabber-check-test-autoloads--dependency-p (cdr form)))))

(defun jabber-check-test-autoloads--read (source)
  "Read one Elisp form from SOURCE."
  (car (read-from-string source)))

(defun jabber-check-test-autoloads--self-test ()
  "Verify reader-sensitive rejection and allowance fixtures."
  (dolist (fixture
           '("(load\n ;; )\n \"jabber-autoloads.el\")"
             "(load-file\n ;; )\n \"jabber-autoloads.el\")"
             "(require\n ;; )\n 'jabber-autoloads)"
             "(load \"jabber-\\x61utoloads.el\")"
             "(load-file \"jabber-\\141utoloads.el\")"
             "(require 'jabber-\\autoloads)"
             "(ignore-errors (require 'unrelated \"jabber-autoloads.el\"))"
             "(ignore-errors (require '#:jabber-autoloads))"))
    (unless (jabber-check-test-autoloads--dependency-p
             (jabber-check-test-autoloads--read fixture))
      (error "Autoload dependency check missed fixture: %s" fixture)))
  (when (jabber-check-test-autoloads--dependency-p
         '(string-suffix-p "jabber-autoloads.el" file))
    (error "Autoload dependency check rejected filename inspection")))

(defun jabber-check-test-autoloads--file-p (file)
  "Return non-nil when FILE directly loads generated Jabber autoloads."
  (with-temp-buffer
    (insert-file-contents file)
    (catch 'found
      (condition-case nil
          (while t
            (when (jabber-check-test-autoloads--dependency-p
                   (read (current-buffer)))
              (throw 'found t)))
        (end-of-file nil)))))

(jabber-check-test-autoloads--self-test)
(let (failed)
  (dolist (file command-line-args-left)
    (when (jabber-check-test-autoloads--file-p file)
      (message "%s: tests must not load generated jabber-autoloads" file)
      (setq failed t)))
  (kill-emacs (if failed 1 0)))

;;; check-test-autoloads ends here
