From a5bd480d77cffb7bcf597782c407cb7ef5938d61 Mon Sep 17 00:00:00 2001 From: Eshel Yaron Date: Mon, 20 Jan 2025 22:11:23 +0100 Subject: [PATCH] Suggest fix for undefined ELisp function --- lisp/emacs-lisp/bytecomp.el | 19 +++++++++++---- lisp/progmodes/elisp-mode.el | 46 ++++++++++++++++++++++-------------- 2 files changed, 43 insertions(+), 22 deletions(-) diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 5defb4669d7..86022700b65 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -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) diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index e69ef840b42..a2f6272415a 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -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))) + (put 'read-symbol-shorthands 'safe-local-variable #'consp) -- 2.39.5