emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/compat 6254608c2e 1/4: compat-macs: Improve error check


From: ELPA Syncer
Subject: [elpa] externals/compat 6254608c2e 1/4: compat-macs: Improve error checking
Date: Sat, 21 Jan 2023 08:57:25 -0500 (EST)

branch: externals/compat
commit 6254608c2e2da008deab6aabf69b23e66fb52433
Author: Daniel Mendler <mail@daniel-mendler.de>
Commit: Daniel Mendler <mail@daniel-mendler.de>

    compat-macs: Improve error checking
---
 compat-29.el    |  2 +-
 compat-macs.el  | 67 +++++++++++++++++++++++++++++++--------------------------
 compat-tests.el | 10 ++++++---
 3 files changed, 44 insertions(+), 35 deletions(-)

diff --git a/compat-29.el b/compat-29.el
index 495ede7e90..ed9e3f936c 100644
--- a/compat-29.el
+++ b/compat-29.el
@@ -171,7 +171,7 @@ This function does not move point.  Also see 
`line-end-position'."
 
 ;;;; Defined in subr.el
 
-(defun readablep (object)
+(compat-defun readablep (object)
   "Say whether OBJECT has a readable syntax.
 This means that OBJECT can be printed out and then read back
 again by the Lisp reader.  This function returns nil if OBJECT is
diff --git a/compat-macs.el b/compat-macs.el
index addef5ecd1..ca5c800214 100644
--- a/compat-macs.el
+++ b/compat-macs.el
@@ -53,25 +53,28 @@ If this is not documented on yourself system, you can check 
\
       (fill-region (point-min) (point-max)))
     (buffer-string)))
 
-(defun compat--check-attributes (attrs allowed)
-  "Check ATTRS for ALLOWED keys and return rest."
+(defun compat--check-attributes (attrs preds)
+  "Check ATTRS given PREDS predicate plist and return rest."
   (while (keywordp (car attrs))
-    (unless (memq (car attrs) allowed)
-      (error "Invalid attribute %s" (car attrs)))
     (unless (cdr attrs)
       (error "Odd number of element in attribute list"))
+    (let ((pred (plist-get preds (car attrs))))
+      (unless (and pred (or (eq pred t) (funcall pred (cadr attrs))))
+        (error "Invalid attribute %s" (car attrs))))
     (setq attrs (cddr attrs)))
   attrs)
 
-(defun compat--guard (attrs args fun)
+(defun compat--guard (attrs preds fun)
   "Guard compatibility definition generation.
-The version constraints specified by ATTRS are checked.
-ARGS is a list of keywords which are looked up and passed to FUN."
+The version constraints specified by ATTRS are checked.  PREDS is
+a plist of predicates for arguments which are passed to FUN."
   (declare (indent 2))
-  (let* ((body (compat--check-attributes attrs `(,@args :when :feature)))
+  (let* ((body (compat--check-attributes
+                attrs `(,@preds :when t :feature symbolp)))
          (feature (plist-get attrs :feature))
          (attrs `(:body ,body ,@attrs))
-         (when (plist-get attrs :when)))
+         (when (plist-get attrs :when))
+         args)
     ;; Require feature at compile time
     (when feature
       (when (eq feature 'subr-x)
@@ -83,7 +86,10 @@ ARGS is a list of keywords which are looked up and passed to 
FUN."
             ;; The current Emacs must be older than the current declared Compat
             ;; version, see `compat-declare-version'.
             (version< emacs-version compat--version))
-      (setq body (apply fun (mapcar (lambda (x) (plist-get attrs x)) args)))
+      (while preds
+        (push (plist-get attrs (car preds)) args)
+        (setq preds (cddr preds)))
+      (setq body (apply fun (nreverse args)))
       (when body
         (if feature
             `(with-eval-after-load ',feature ,@body)
@@ -92,7 +98,9 @@ ARGS is a list of keywords which are looked up and passed to 
FUN."
 (defun compat--guard-defun (type name arglist docstring rest)
   "Define function NAME of TYPE with ARGLIST and DOCSTRING.
 REST are attributes and the function BODY."
-  (compat--guard rest '(:explicit :obsolete :body)
+  (compat--guard rest `(:explicit booleanp
+                        :obsolete ,(lambda (x) (or (booleanp x) (stringp x)))
+                        :body t)
     (lambda (explicit obsolete body)
       ;; Remove unsupported declares.  It might be possible to set these
       ;; properties otherwise.  That should be looked into and implemented
@@ -142,7 +150,7 @@ definition is generated.
   part of the :when expression."
   (declare (debug ([&rest keywordp sexp] def-body))
            (indent 1))
-  (compat--guard rest '(:body)
+  (compat--guard rest '(:body t)
     (lambda (body)
       (if (eq cond t)
           body
@@ -153,11 +161,11 @@ definition is generated.
 ATTRS is a plist of attributes, which specify the conditions
 under which the definition is generated.
 
-- :obsolete :: Mark the alias as obsolete if non-nil.
+- :obsolete :: Mark the alias as obsolete if t.
 
 - :feature and :when :: See `compat-guard'."
   (declare (debug (name symbolp [&rest keywordp sexp])))
-  (compat--guard attrs '(:obsolete)
+  (compat--guard attrs '(:obsolete booleanp)
     (lambda (obsolete)
       ;; The fboundp check is performed at runtime to make sure that we never
       ;; redefine an existing definition if Compat is loaded on a newer Emacs
@@ -181,7 +189,7 @@ specify the conditions under which the definition is 
generated.
   functions which changed their calling convention or their
   behavior.
 
-- :obsolete :: Mark the function as obsolete if non-nil, can be a
+- :obsolete :: Mark the function as obsolete if t, can be a
   string describing the obsoletion.
 
 - :feature and :when :: See `compat-guard'."
@@ -206,20 +214,23 @@ The variable must be documented in DOCSTRING.  ATTRS is a 
plist
 of attributes, which specify the conditions under which the
 definition is generated.
 
-- :constant :: Mark the variable as constant if non-nil.
+- :constant :: Mark the variable as constant if t.
 
-- :local :: Make the variable permanently local if the value is
-  `permanent'.  For other non-nil values make the variable
-  buffer-local.
+- :local :: Make the variable buffer-local if t.  If the value is
+  `permanent' make the variable additionally permanently local.
 
-- :obsolete :: Mark the variable as obsolete if non-nil, can be a
+- :obsolete :: Mark the variable as obsolete if t, can be a
   string describing the obsoletion.
 
 - :feature and :when :: See `compat-guard'."
   (declare (debug (name form stringp [&rest keywordp sexp]))
            (doc-string 3) (indent 2))
-  (compat--guard attrs '(:local :constant :obsolete)
-    (lambda (local constant obsolete)
+  (compat--guard attrs `(:constant booleanp
+                         :local ,(lambda (x) (memq x '(nil t permanent)))
+                         :obsolete ,(lambda (x) (or (booleanp x) (stringp x))))
+    (lambda (constant local obsolete)
+      (when (and constant local)
+        (error ":constant and :local cannot be specified together"))
       ;; The boundp check is performed at runtime to make sure that we never
       ;; redefine an existing definition if Compat is loaded on a newer Emacs
       ;; version.
@@ -230,15 +241,9 @@ definition is generated.
           ,@(when obsolete
               `((make-obsolete-variable
                  ',name ,(if (stringp obsolete) obsolete "No substitute")
-                 ,compat--version)))
-          ,@(cond
-             ((eq local 'permanent)
-              `((put ',name 'permanent-local t)))
-             ((eq local t)
-              `((make-variable-buffer-local ',name)))
-             ((not local)
-              nil)
-             (t (error "Invalid value for :local"))))))))
+                 ,compat--version))))
+        ,@(and local `((make-variable-buffer-local ',name)))
+        ,@(and (eq local 'permanent) `((put ',name 'permanent-local t)))))))
 
 (provide 'compat-macs)
 ;;; compat-macs.el ends here
diff --git a/compat-tests.el b/compat-tests.el
index e98d1fc94a..bb22dbc0ad 100644
--- a/compat-tests.el
+++ b/compat-tests.el
@@ -2811,16 +2811,20 @@
 
 (ert-deftest major-mode-suspend ()
   (with-temp-buffer
+    (should (local-variable-if-set-p 'major-mode--suspended))
+    (should (get 'major-mode--suspended 'permanent-local))
     (text-mode)
     (should sentence-end-double-space)
     (setq-local sentence-end-double-space nil)
     (major-mode-suspend)
-    (should-not line-spacing)
+    (should-equal major-mode--suspended #'text-mode)
+    (should sentence-end-double-space)
     (prog-mode)
-    (should-equal major-mode 'prog-mode)
+    (should-equal major-mode #'prog-mode)
     (major-mode-restore)
+    (should-not major-mode--suspended)
     (should sentence-end-double-space)
-    (should-equal major-mode 'text-mode)))
+    (should-equal major-mode #'text-mode)))
 
 (provide 'compat-tests)
 ;;; compat-tests.el ends here



reply via email to

[Prev in Thread] Current Thread [Next in Thread]