From 0b4b380ce4989afc59848d2b6a350bd1dd7dc7ca Mon Sep 17 00:00:00 2001 From: Philipp Stephani Date: Sat, 2 Jun 2018 11:59:02 +0200 Subject: [PATCH] Make warning about unescaped character literals more helpful. See Bug#31676. * lisp/emacs-lisp/byte-run.el (byte-run--unescaped-character-literals-warning): New defun. * src/lread.c (load_warn_unescaped_character_literals): Use new defun. (syms_of_lread): Define symbol for new defun. * lisp/emacs-lisp/bytecomp.el (byte-compile-from-buffer): Use new defun. * test/src/lread-tests.el (lread-tests--unescaped-char-literals): test/lisp/emacs-lisp/bytecomp-tests.el (bytecomp-tests--unescaped-char-literals): Adapt unit tests. --- lisp/emacs-lisp/byte-run.el | 15 +++++++++++++++ lisp/emacs-lisp/bytecomp.el | 11 +++-------- src/lread.c | 24 +++++++++--------------- test/lisp/emacs-lisp/bytecomp-tests.el | 4 +++- test/src/lread-tests.el | 4 +++- 5 files changed, 33 insertions(+), 25 deletions(-) diff --git a/lisp/emacs-lisp/byte-run.el b/lisp/emacs-lisp/byte-run.el index b638b56be1f..7e256f83272 100644 --- a/lisp/emacs-lisp/byte-run.el +++ b/lisp/emacs-lisp/byte-run.el @@ -494,6 +494,21 @@ is enabled." ;; The implementation for the interpreter is basically trivial. (car (last body))) + +(defun byte-run--unescaped-character-literals-warning () + "Return a warning about unescaped character literals. +If there were any unescaped character literals in the last form +read, return an appropriate warning message as a string. +Otherwise, return nil. For internal use only." + ;; This is called from lread.c and therefore needs to be preloaded. + (if lread--unescaped-character-literals + (let ((sorted (sort lread--unescaped-character-literals #'<))) + (format-message "unescaped character literals %s detected, %s expected!" + (mapconcat (lambda (char) (format "`?%c'" char)) + sorted ", ") + (mapconcat (lambda (char) (format "`?\\%c'" char)) + sorted ", "))))) + ;; I nuked this because it's not a good idea for users to think of using it. ;; These options are a matter of installation preference, and have nothing to diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 8bbe6292d9d..4c61e1a4471 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -2082,14 +2082,9 @@ With argument ARG, insert value in current buffer after the form." (not (eobp))) (setq byte-compile-read-position (point) byte-compile-last-position byte-compile-read-position) - (let* ((lread--unescaped-character-literals nil) - (form (read inbuffer))) - (when lread--unescaped-character-literals - (byte-compile-warn - "unescaped character literals %s detected!" - (mapconcat (lambda (char) (format "`?%c'" char)) - (sort lread--unescaped-character-literals #'<) - ", "))) + (let ((form (read inbuffer)) + (warning (byte-run--unescaped-character-literals-warning))) + (when warning (byte-compile-warn "%s" warning)) (byte-compile-toplevel-file-form form))) ;; Compile pending forms at end of file. (byte-compile-flush-pending) diff --git a/src/lread.c b/src/lread.c index 8cb4b63cc3a..8b38cacde07 100644 --- a/src/lread.c +++ b/src/lread.c @@ -1034,18 +1034,12 @@ load_error_old_style_backquotes (void) static void load_warn_unescaped_character_literals (Lisp_Object file) { - if (NILP (Vlread_unescaped_character_literals)) return; - CHECK_CONS (Vlread_unescaped_character_literals); - Lisp_Object format = - build_string ("Loading `%s': unescaped character literals %s detected!"); - Lisp_Object separator = build_string (", "); - Lisp_Object inner_format = build_string ("`?%c'"); - CALLN (Fmessage, - format, file, - Fmapconcat (list3 (Qlambda, list1 (Qchar), - list3 (Qformat, inner_format, Qchar)), - Fsort (Vlread_unescaped_character_literals, Qlss), - separator)); + Lisp_Object warning + = call0 (Qbyte_run_unescaped_character_literals_warning); + if (NILP (warning)) + return; + Lisp_Object format = build_string ("Loading `%s': %s"); + CALLN (Fmessage, format, file, warning); } DEFUN ("get-load-suffixes", Fget_load_suffixes, Sget_load_suffixes, 0, 0, 0, @@ -5014,9 +5008,9 @@ For internal use only. */); DEFSYM (Qlread_unescaped_character_literals, "lread--unescaped-character-literals"); - DEFSYM (Qlss, "<"); - DEFSYM (Qchar, "char"); - DEFSYM (Qformat, "format"); + /* Defined in lisp/emacs-lisp/byte-run.el. */ + DEFSYM (Qbyte_run_unescaped_character_literals_warning, + "byte-run--unescaped-character-literals-warning"); DEFVAR_BOOL ("load-prefer-newer", load_prefer_newer, doc: /* Non-nil means `load' prefers the newest version of a file. diff --git a/test/lisp/emacs-lisp/bytecomp-tests.el b/test/lisp/emacs-lisp/bytecomp-tests.el index f66a06bc1bc..5fb64ff2881 100644 --- a/test/lisp/emacs-lisp/bytecomp-tests.el +++ b/test/lisp/emacs-lisp/bytecomp-tests.el @@ -540,7 +540,9 @@ literals (Bug#20852)." (should (equal (cdr err) (list (concat "unescaped character literals " "`?\"', `?(', `?)', `?;', `?[', `?]' " - "detected!")))))))) + "detected, " + "`?\\\"', `?\\(', `?\\)', `?\\;', `?\\[', " + "`?\\]' expected!")))))))) (ert-deftest bytecomp-tests--old-style-backquotes () "Check that byte compiling warns about old-style backquotes." diff --git a/test/src/lread-tests.el b/test/src/lread-tests.el index ae918f03120..82b75b195ca 100644 --- a/test/src/lread-tests.el +++ b/test/src/lread-tests.el @@ -140,7 +140,9 @@ literals (Bug#20852)." (should (equal (lread-tests--last-message) (concat (format-message "Loading `%s': " file-name) "unescaped character literals " - "`?\"', `?(', `?)', `?;', `?[', `?]' detected!"))))) + "`?\"', `?(', `?)', `?;', `?[', `?]' detected, " + "`?\\\"', `?\\(', `?\\)', `?\\;', `?\\[', `?\\]' " + "expected!"))))) (ert-deftest lread-tests--funny-quote-symbols () "Check that 'smart quotes' or similar trigger errors in symbol names." -- 2.39.2