From 3e79fd3d4e810c2ef4cf9925a747c93e036fddca Mon Sep 17 00:00:00 2001 From: Helmut Eller Date: Thu, 3 Aug 2023 08:33:40 +0200 Subject: [PATCH] Check keyword args of make-process The functions make-process and make-network-process have many keyword args and it's easy to misspell some of them. Use a compiler macro to warn about some possible mistakes. * lisp/emacs-lisp/bytecomp.el (bytecomp--check-keyword-args): New helper. (make-process, make-network-process): Define a compiler macro that performs some checks but doesn't anything else. * test/lisp/emacs-lisp/bytecomp-tests.el: Add some tests. * test/lisp/emacs-lisp/bytecomp-resources/: (warn-make-process-missing-keyword-arg.el, warn-make-process-missing-keyword-value.el, warn-make-process-repeated-keyword-arg.el, warn-make-process-unknown-keyword-arg.el): New test files --- lisp/emacs-lisp/bytecomp.el | 61 +++++++++++++++++++ .../warn-make-process-missing-keyword-arg.el | 3 + ...warn-make-process-missing-keyword-value.el | 3 + .../warn-make-process-repeated-keyword-arg.el | 3 + .../warn-make-process-unknown-keyword-arg.el | 4 ++ test/lisp/emacs-lisp/bytecomp-tests.el | 16 +++++ 6 files changed, 90 insertions(+) create mode 100644 test/lisp/emacs-lisp/bytecomp-resources/warn-make-process-missing-keyword-arg.el create mode 100644 test/lisp/emacs-lisp/bytecomp-resources/warn-make-process-missing-keyword-value.el create mode 100644 test/lisp/emacs-lisp/bytecomp-resources/warn-make-process-repeated-keyword-arg.el create mode 100644 test/lisp/emacs-lisp/bytecomp-resources/warn-make-process-unknown-keyword-arg.el diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index f6ba6ff9ea0..0df7b0bfe2a 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -5782,6 +5782,67 @@ and corresponding effects." form ; arity error `(forward-word (- (or ,arg 1))))) +(defun bytecomp--check-keyword-args (form arglist allowed-keys required-keys) + (let ((fun (car form))) + (cl-flet ((missing (form keyword) + (byte-compile-warn-x + form + "`%S´ called without required keyword argument %S" + fun keyword)) + (unrecognized (form keyword) + (byte-compile-warn-x + form + "`%S´ called with unknown keyword argument %S" + fun keyword)) + (duplicate (form keyword) + (byte-compile-warn-x + form + "`%S´ called with repeated keyword argument %S" + fun keyword)) + (missing-val (form keyword) + (byte-compile-warn-x + form + "missing value for keyword argument %S" + keyword))) + (let* ((seen '()) + (l arglist)) + (while (consp l) + (let ((key (car l))) + (cond ((and (keywordp key) (memq key allowed-keys)) + (cond ((memq key seen) + (duplicate l key)) + (t + (push key seen)))) + (t (unrecognized l key))) + (when (null (cdr l)) + (missing-val l key))) + (setq l (cddr l))) + (dolist (key required-keys) + (unless (memq key seen) + (missing form key)))))) + form) + +(put 'make-process 'compiler-macro + #'(lambda (form &rest args) + (bytecomp--check-keyword-args + form args + '(:name + :buffer :command :coding :noquery :stop :connection-type + :filter :sentinel :stderr :file-handler) + '(:name :command)))) + +(put 'make-network-process 'compiler-macro + #'(lambda (form &rest args) + (bytecomp--check-keyword-args + form args + '(:name + :buffer :host :service :type :family :local :remote :coding + :nowait :noquery :stop :filter :filter-multibyte :sentinel + :log :plist :tls-parameters :server :broadcast :dontroute + :keepalive :linger :oobinline :priority :reuseaddr :bindtodevice + :use-external-socket) + '(:name :service)))) + (provide 'byte-compile) (provide 'bytecomp) diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-make-process-missing-keyword-arg.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-make-process-missing-keyword-arg.el new file mode 100644 index 00000000000..9369e78ff54 --- /dev/null +++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-make-process-missing-keyword-arg.el @@ -0,0 +1,3 @@ +;;; -*- lexical-binding: t -*- +(defun foo () + (make-process :name "ls")) diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-make-process-missing-keyword-value.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-make-process-missing-keyword-value.el new file mode 100644 index 00000000000..4226349afef --- /dev/null +++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-make-process-missing-keyword-value.el @@ -0,0 +1,3 @@ +;;; -*- lexical-binding: t -*- +(defun foo () + (make-process :name "ls" :command)) diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-make-process-repeated-keyword-arg.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-make-process-repeated-keyword-arg.el new file mode 100644 index 00000000000..18250f14ee9 --- /dev/null +++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-make-process-repeated-keyword-arg.el @@ -0,0 +1,3 @@ +;;; -*- lexical-binding: t -*- +(defun foo () + (make-process :name "ls" :command "ls" :name "ls")) diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-make-process-unknown-keyword-arg.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-make-process-unknown-keyword-arg.el new file mode 100644 index 00000000000..4721035780b --- /dev/null +++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-make-process-unknown-keyword-arg.el @@ -0,0 +1,4 @@ +;;; -*- lexical-binding: t -*- +(defun foo () + (make-process :name "ls" :command "ls" + :coding-system 'binary)) diff --git a/test/lisp/emacs-lisp/bytecomp-tests.el b/test/lisp/emacs-lisp/bytecomp-tests.el index 19e08e8d199..26325c1ef11 100644 --- a/test/lisp/emacs-lisp/bytecomp-tests.el +++ b/test/lisp/emacs-lisp/bytecomp-tests.el @@ -1204,6 +1204,22 @@ byte-compiled. Run with dynamic binding." "nowarn-inline-after-defvar.el" "Lexical argument shadows" 'reverse) +(bytecomp--define-warning-file-test + "warn-make-process-missing-keyword-arg.el" + "called without required keyword argument :command") + +(bytecomp--define-warning-file-test + "warn-make-process-unknown-keyword-arg.el" + "called with unknown keyword argument :coding-system") + +(bytecomp--define-warning-file-test + "warn-make-process-repeated-keyword-arg.el" + "called with repeated keyword argument :name") + +(bytecomp--define-warning-file-test + "warn-make-process-missing-keyword-value.el" + "missing value for keyword argument :command") + ;;;; Macro expansion. -- 2.39.5