]> git.eshelyaron.com Git - emacs.git/commitdiff
Suggest fix for undefined ELisp function
authorEshel Yaron <me@eshelyaron.com>
Mon, 20 Jan 2025 21:11:23 +0000 (22:11 +0100)
committerEshel Yaron <me@eshelyaron.com>
Mon, 20 Jan 2025 21:11:23 +0000 (22:11 +0100)
lisp/emacs-lisp/bytecomp.el
lisp/progmodes/elisp-mode.el

index 5defb4669d75ee1ace59f1b2fb11abfcca518ecf..86022700b65fc6d797482b15ae675387b89450a1 100644 (file)
@@ -1411,6 +1411,13 @@ FORMAT and ARGS are as in `byte-compile-warn'."
   (let ((byte-compile-form-stack (cons arg byte-compile-form-stack)))
     (apply #'byte-compile-warn format args)))
 
+(defvar byte-compile-current-warning-fix nil)
+
+(defun byte-compile-warn-with-fix (fix arg format &rest args)
+  (let ((byte-compile-current-warning-fix fix)
+        (byte-compile-form-stack (cons arg byte-compile-form-stack)))
+    (byte-compile-warn-x arg format args)))
+
 ;;;###autoload
 (defun byte-compile-warn-obsolete (symbol type)
   "Warn that SYMBOL (a variable, function or generalized variable) is obsolete.
@@ -1879,10 +1886,14 @@ It is too wide if it has any lines longer than the largest of
       (dolist (urf byte-compile-unresolved-functions)
         (let ((f (car urf)))
           (when (not (memq f byte-compile-new-defuns))
-            (byte-compile-warn-x
-             f
-             (if (fboundp f) "the function `%s' might not be defined at runtime." "the function `%s' is not known to be defined.")
-               (car urf)))))))
+            (if (fboundp f)
+                (byte-compile-warn-x
+                 f "the function `%s' might not be defined at runtime."
+                 (car urf))
+              (byte-compile-warn-with-fix
+               '("Fix it" elisp-create-missing-defun)
+               f "the function `%s' is not known to be defined."
+               (car urf))))))))
   nil)
 
 \f
index e69ef840b42d3cd359418d6c1e5a755c3f2bd2c8..a2f6272415a22d4644f5de8de765ef8bf7b40909 100644 (file)
@@ -2308,7 +2308,7 @@ Calls REPORT-FN directly."
                     (goto-char (point-min))
                     (search-forward ":elisp-flymake-output-start")
                     (read (point-marker)))
-                  for (string pos _fill level) in data
+                  for (string pos _fill level fix) in data
                   do (goto-char pos)
                   for beg = (if (< (point) (point-max))
                                 (point)
@@ -2328,7 +2328,8 @@ Calls REPORT-FN directly."
                                     (point-max))
                              end)
                            level
-                           string)))))))
+                           string
+                           fix nil (when fix #'list))))))))
 
 (defvar-local elisp-flymake--byte-compile-process nil
   "Buffer-local process started for byte-compiling the buffer.")
@@ -2429,7 +2430,7 @@ Runs in a batch-mode Emacs.  Interactively use variable
          (collected)
          (byte-compile-log-warning-function
           (lambda (string &optional position fill level)
-            (push (list string position fill level)
+            (push (list string position fill level byte-compile-current-warning-fix)
                   collected)
             t)))
     (unwind-protect
@@ -2548,27 +2549,32 @@ where the body of the defun should go.
 Interactively, if point is in a list (FUN . ARGS), then FUN-NAME is the
 name of FUN and ARG-NAMES is a list with placeholder argument names, one
 for each element of ARGS."
-  (interactive
-   (save-excursion
-     (named-let rec ((ps (reverse (nth 9 (syntax-ppss)))))
-       (if (null ps)
-           (user-error "No function call at point")
-         (goto-char (car ps))
-         (pcase (read (current-buffer))
-           (`(,(and head (pred symbolp)) . ,tail)
-            (list (symbol-name head)
-                  (mapcar (compose
-                           (apply-partially #'concat "arg")
-                           #'number-to-string)
-                          (number-sequence 1 (length tail)))))
-           (_ (rec (cdr ps)))))))
-   emacs-lisp-mode)
+  (interactive (elisp-create-defun-interactive-arguments) emacs-lisp-mode)
   (push-mark)
   (beginning-of-defun-raw)
   (goto-char (scan-sexps (point) 1))
   (insert "\n\n(defun " fun-name " (" (string-join arg-names " ") "))")
   (backward-char))
 
+(defun elisp-create-defun-interactive-arguments ()
+  (save-excursion
+    (named-let rec ((ps (reverse (nth 9 (syntax-ppss)))))
+      (if (null ps)
+          (user-error "No function call at point")
+        (goto-char (car ps))
+        (pcase (read (current-buffer))
+          (`(,(and head (pred symbolp)) . ,tail)
+           (list (symbol-name head)
+                 (mapcar (compose
+                          (apply-partially #'concat "arg")
+                          #'number-to-string)
+                         (number-sequence 1 (length tail)))))
+          (_ (rec (cdr ps))))))))
+
+(defun elisp-create-missing-defun ()
+  (apply #'elisp-create-defun (elisp-create-defun-interactive-arguments)))
+
+
 (defvar avy-action)
 
 (defvar elisp-extract-local-variable-name-history nil)
@@ -2659,6 +2665,10 @@ of TARGET."
     (prog-indent-sexp 'defun)
     (goto-char pos)))
 
+;; (defun elisp-dwim (pos)
+;;   (interactive "d" emacs-lisp-mode)
+;;   (if (flymake-diagnostics pos)))
+
 \f
 (put 'read-symbol-shorthands 'safe-local-variable #'consp)