]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix bug#28557
authorStefan Monnier <monnier@iro.umontreal.ca>
Mon, 20 Dec 2021 16:04:37 +0000 (11:04 -0500)
committerStefan Monnier <monnier@iro.umontreal.ca>
Mon, 20 Dec 2021 16:04:37 +0000 (11:04 -0500)
* test/lisp/emacs-lisp/cconv-tests.el: Remove `:expected-result :failed`
from the bug#28557 tests.
(cconv-tests-cl-function-:documentation): Account for the presence of
the arglist (aka "usage") in the docstring.

* lisp/emacs-lisp/cl-macs.el (cl--transform-lambda):
* lisp/emacs-lisp/cl-generic.el (cl-defgeneric):
Handle non-constant `:documentation`.

* lisp/emacs-lisp/generator.el (iter-lambda):
* lisp/emacs-lisp/fcr.el (fcr-lambda):
* lisp/emacs-lisp/cconv.el (cconv--convert-funcbody):
Use `macroexp-parse-body`.

* lisp/calendar/icalendar.el (icalendar--decode-isodatetime):
Fix misuse of `cl-lib` without requiring it.

lisp/calendar/icalendar.el
lisp/emacs-lisp/cconv.el
lisp/emacs-lisp/cl-generic.el
lisp/emacs-lisp/cl-macs.el
lisp/emacs-lisp/fcr.el
lisp/emacs-lisp/generator.el
lisp/emacs-lisp/nadvice.el
test/lisp/emacs-lisp/cconv-tests.el

index 7a483d40627148ec43f720e8890dc393525a18cb..01387341d6588698c0b2aed07caf24afc3383b04 100644 (file)
@@ -645,10 +645,10 @@ FIXME: multiple comma-separated values should be allowed!"
           (setq second (read (substring isodatetimestring 13 15))))
        ;; FIXME: Support subseconds.
         (when (> (length isodatetimestring) 15)
-          (cl-case (aref isodatetimestring 15)
+          (pcase (aref isodatetimestring 15)
             (?Z
              (setq source-zone t))
-            ((?- ?+)
+            ((or ?- ?+)
              (setq source-zone
                    (concat "UTC" (substring isodatetimestring 15))))))
         ;; shift if necessary
index d1c7bc0e51a4c4651f4da405ee1a402e5ef33144..4fdcf2b24baf6e6be8878f37241018240775b786 100644 (file)
@@ -294,15 +294,10 @@ of converted forms."
                              (cconv-convert form env nil))
                            funcbody))
     (if wrappers
-        (let ((special-forms '()))
-          ;; Keep special forms at the beginning of the body.
-          (while (or (and (cdr funcbody) (stringp (car funcbody))) ;docstring.
-                     (memq (car-safe (car funcbody))
-                           '(interactive declare :documentation)))
-            (push (pop funcbody) special-forms))
-          (let ((body (macroexp-progn funcbody)))
+        (pcase-let ((`(,decls . ,body) (macroexp-parse-body funcbody)))
+          (let ((body (macroexp-progn body)))
             (dolist (wrapper wrappers) (setq body (funcall wrapper body)))
-            `(,@(nreverse special-forms) ,@(macroexp-unprogn body))))
+            `(,@decls ,@(macroexp-unprogn body))))
       funcbody)))
 
 (defun cconv--lifted-arg (var env)
index 643c006e431ac98a75798759358706ac8e06c352..f6643c14546aebf6171c2ffbd15a734b2dcd813b 100644 (file)
@@ -286,7 +286,9 @@ DEFAULT-BODY, if present, is used as the body of a default method.
          (progn
            (defalias ',name
              (cl-generic-define ',name ',args ',(nreverse options))
-             ,(help-add-fundoc-usage doc args))
+             ,(if (consp doc)           ;An expression rather than a constant.
+                  `(docstring-add-fundoc-usage ,doc ',args)
+                (docstring-add-fundoc-usage doc args)))
            :autoload-end
            ,@(mapcar (lambda (method) `(cl-defmethod ,name ,@method))
                      (nreverse methods)))
index 6bd0d0c3283da248d1dcc06bcac2753652c0f31e..96559fbfb6e285f51dbf2cfb30420e91ae1445c7 100644 (file)
@@ -301,24 +301,33 @@ FORM is of the form (ARGS . BODY)."
              (t ;; `simple-args' doesn't handle all the parsing that we need,
               ;; so we pass the rest to cl--do-arglist which will do
               ;; "manual" parsing.
-              (let ((slen (length simple-args)))
-                (when (memq '&optional simple-args)
-                  (cl-decf slen))
-                (setq header
+              (let ((slen (length simple-args))
+                    (usage-str
                       ;; Macro expansion can take place in the middle of
                       ;; apparently harmless computation, so it should not
                       ;; touch the match-data.
                       (save-match-data
+                        (docstring--quote
+                         (let ((print-gensym nil) (print-quoted t)
+                               (print-escape-newlines t))
+                           (format "%S" (cons 'fn (cl--make-usage-args
+                                                   orig-args))))))))
+                (when (memq '&optional simple-args)
+                  (cl-decf slen))
+                (setq header
+                      (cond
+                       ((eq :documentation (caar header))
+                        `((:documentation (docstring-add-fundoc-usage
+                                           ,(cadr (car header))
+                                           ,usage-str))
+                          ,@(cdr header)))
+                       (t
                         (cons (docstring-add-fundoc-usage
                                (if (stringp (car header)) (pop header))
                                ;; Be careful with make-symbol and (back)quote,
                                ;; see bug#12884.
-                               (docstring--quote
-                                (let ((print-gensym nil) (print-quoted t)
-                                      (print-escape-newlines t))
-                                  (format "%S" (cons 'fn (cl--make-usage-args
-                                                          orig-args))))))
-                              header)))
+                               usage-str)
+                              header))))
                 ;; FIXME: we'd want to choose an arg name for the &rest param
                 ;; and pass that as `expr' to cl--do-arglist, but that ends up
                 ;; generating code with a redundant let-binding, so we instead
index 8f01d56a54c8071fcd87184d6ffd491e9c793958..548348a904182e2ced16be5e82f30e84828b8ce3 100644 (file)
 
 (defmacro fcr-lambda (type fields args &rest body)
   (declare (indent 3) (debug (sexp (&rest (sexp form)) sexp def-body)))
-  ;; FIXME: Provide the fields in the order specified by `type'.
-  (let* ((class (cl--find-class type))
-         (slots (fcr--class-slots class))
-         (prebody '())
-         (slotbinds (nreverse
-                     (mapcar (lambda (slot)
-                               (list (cl--slot-descriptor-name slot)))
-                             slots)))
-         (tempbinds (mapcar
-                     (lambda (field)
-                       (let* ((name (car field))
-                              (bind (assq name slotbinds)))
-                         (cond
-                          ((not bind)
-                           (error "Unknown slots: %S" name))
-                          ((cdr bind)
-                           (error "Duplicate slots: %S" name))
-                          (t
-                           (let ((temp (gensym "temp")))
-                             (setcdr bind (list temp))
-                             (cons temp (cdr field)))))))
-                     fields)))
-    ;; FIXME: Since we use the docstring internally to store the
-    ;; type we can't handle actual docstrings.  We could fix this by adding
-    ;; a docstring slot to FCRs.
-    (while (memq (car-safe (car-safe body)) '(interactive declare))
-      (push (pop body) prebody))
+  ;; FIXME: Should `fcr-defstruct' distinguish "optional" from
+  ;; "mandatory" slots, and/or provide default values for slots missing
+  ;; from `fields'?
+  (pcase-let*
+      ((class (cl--find-class type))
+       (slots (fcr--class-slots class))
+       ;; FIXME: Since we use the docstring internally to store the
+       ;; type we can't handle actual docstrings.  We could fix this by adding
+       ;; a docstring slot to FCRs.
+       (`(,prebody . ,body) (macroexp-parse-body body))
+       (slotbinds (nreverse
+                   (mapcar (lambda (slot)
+                             (list (cl--slot-descriptor-name slot)))
+                           slots)))
+       (tempbinds (mapcar
+                   (lambda (field)
+                     (let* ((name (car field))
+                            (bind (assq name slotbinds)))
+                       (cond
+                        ((not bind)
+                         (error "Unknown slots: %S" name))
+                        ((cdr bind)
+                         (error "Duplicate slots: %S" name))
+                        (t
+                         (let ((temp (gensym "temp")))
+                           (setcdr bind (list temp))
+                           (cons temp (cdr field)))))))
+                   fields)))
     ;; FIXME: Optimize temps away when they're provided in the right order?
     ;; FIXME: Slots not specified in `fields' tend to emit "Variable FOO left
     ;; uninitialized"!
index cb0241017a023569163d5dbb1225c0198b9f7a05..a768c6ae832eb394cd9586e35859f389b849350c 100644 (file)
@@ -692,8 +692,10 @@ of values.  Callers can retrieve each value using `iter-next'."
   (declare (indent defun)
            (debug (&define lambda-list lambda-doc &rest sexp)))
   (cl-assert lexical-binding)
-  `(lambda ,arglist
-     ,(cps-generate-evaluator body)))
+  (pcase-let* ((`(,declarations . ,exps) (macroexp-parse-body body)))
+    `(lambda ,arglist
+       ,@declarations
+       ,(cps-generate-evaluator exps))))
 
 (defmacro iter-make (&rest body)
   "Return a new iterator."
index b07bc74e7b420ec9bb0b94f6f829fe3d134e4aaf..36f9a0514a2a8ee6126b4f95c82d27c85f8e5dd6 100644 (file)
@@ -484,6 +484,8 @@ is defined as a macro, alias, command, ..."
                           (get symbol 'advice--pending))
                          (t (symbol-function symbol)))
                   function props)
+    ;; FIXME: We could use a defmethod on `function-docstring' instead,
+    ;; except when (or (not nf) (autoloadp nf))!
     (put symbol 'function-documentation `(advice--make-docstring ',symbol))
     (add-function :around (get symbol 'defalias-fset-function)
                   #'advice--defalias-fset))
index 0701892b8c4131dbd7f65daf85177f902118c063..d7f9af18994e9cfe926bc5e21d2c3048677c03f9 100644 (file)
@@ -83,9 +83,6 @@
   (iter-yield 'cl-iter-defun-result))
 (ert-deftest cconv-tests-cl-iter-defun-:documentation ()
   "Docstring for cl-iter-defun can be specified with :documentation."
-  ;; FIXME: See Bug#28557.
-  :tags '(:unstable)
-  :expected-result :failed
   (should (string= (documentation 'cconv-tests-cl-iter-defun)
                    "cl-iter-defun documentation"))
   (should (eq (iter-next (cconv-tests-cl-iter-defun))
   (iter-yield 'iter-defun-result))
 (ert-deftest cconv-tests-iter-defun-:documentation ()
   "Docstring for iter-defun can be specified with :documentation."
-  ;; FIXME: See Bug#28557.
-  :tags '(:unstable)
-  :expected-result :failed
   (should (string= (documentation 'cconv-tests-iter-defun)
                    "iter-defun documentation"))
   (should (eq (iter-next (cconv-tests-iter-defun)) 'iter-defun-result)))
 
 (ert-deftest cconv-tests-iter-lambda-:documentation ()
   "Docstring for iter-lambda can be specified with :documentation."
-  ;; FIXME: See Bug#28557.
-  :expected-result :failed
   (let ((iter-fun
          (iter-lambda ()
            (:documentation (concat "iter-lambda" " documentation"))
 
 (ert-deftest cconv-tests-cl-function-:documentation ()
   "Docstring for cl-function can be specified with :documentation."
-  ;; FIXME: See Bug#28557.
-  :expected-result :failed
   (let ((fun (cl-function (lambda (&key arg)
                             (:documentation (concat "cl-function"
                                                     " documentation"))
                             (list arg 'cl-function-result)))))
-    (should (string= (documentation fun) "cl-function documentation"))
+    (should (string-match "\\`cl-function documentation$" (documentation fun)))
     (should (equal (funcall fun :arg t) '(t cl-function-result)))))
 
 (ert-deftest cconv-tests-function-:documentation ()
   (+ 1 n))
 (ert-deftest cconv-tests-cl-defgeneric-:documentation ()
   "Docstring for cl-defgeneric can be specified with :documentation."
-  ;; FIXME: See Bug#28557.
-  :expected-result :failed
   (let ((descr (describe-function 'cconv-tests-cl-defgeneric)))
     (set-text-properties 0 (length descr) nil descr)
     (should (string-match-p "cl-defgeneric documentation" descr))