emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master c2bbdc3: Warn about missing backslashes during load


From: Philipp Stephani
Subject: [Emacs-diffs] master c2bbdc3: Warn about missing backslashes during load
Date: Mon, 1 May 2017 14:39:28 -0400 (EDT)

branch: master
commit c2bbdc3316487e34eba1470dd059c0c290431e00
Author: Philipp Stephani <address@hidden>
Commit: Philipp Stephani <address@hidden>

    Warn about missing backslashes during load
    
    * src/lread.c (load_warn_unescaped_character_literals, Fload, read1)
    (syms_of_lread): Warn if unescaped character literals are
    found (Bug#20152).
    * lisp/emacs-lisp/bytecomp.el (byte-compile-from-buffer): Check for
    unescaped character literals during byte compilation.
    * test/src/lread-tests.el (lread-tests--unescaped-char-literals): New
    unit test.
    (lread-tests--with-temp-file, lread-tests--last-message): Helper
    functions for unit test.
    * test/lisp/emacs-lisp/bytecomp-tests.el
    (bytecomp-tests--unescaped-char-literals): New unit test.
    * test/lisp/emacs-lisp/bytecomp-tests.el (bytecomp-tests--with-temp-file):
    Helper macro for unit test.
---
 lisp/emacs-lisp/bytecomp.el            |  7 ++++++
 src/lread.c                            | 40 ++++++++++++++++++++++++++++++++++
 test/lisp/emacs-lisp/bytecomp-tests.el | 23 +++++++++++++++++++
 test/src/lread-tests.el                | 26 ++++++++++++++++++++++
 4 files changed, 96 insertions(+)

diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index 15dc240..2510254 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -2027,12 +2027,19 @@ With argument ARG, insert value in current buffer after 
the form."
          (setq byte-compile-read-position (point)
                byte-compile-last-position byte-compile-read-position)
          (let* ((old-style-backquotes nil)
+                 (lread--unescaped-character-literals nil)
                  (form (read inbuffer)))
             ;; Warn about the use of old-style backquotes.
             (when old-style-backquotes
               (byte-compile-warn "!! The file uses old-style backquotes !!
 This functionality has been obsolete for more than 10 years already
 and will be removed soon.  See (elisp)Backquote in the manual."))
+            (when lread--unescaped-character-literals
+              (byte-compile-warn
+               "unescaped character literals %s detected!"
+               (mapconcat #'string
+                          (sort lread--unescaped-character-literals #'<)
+                          ", ")))
            (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 3b2e123..6467043 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -955,6 +955,21 @@ load_warn_old_style_backquotes (Lisp_Object file)
     }
 }
 
+static void
+load_warn_unescaped_character_literals (Lisp_Object file)
+{
+  if (NILP (Vlread_unescaped_character_literals)) return;
+  CHECK_CONS (Vlread_unescaped_character_literals);
+  AUTO_STRING (format,
+               "Loading `%s': unescaped character literals %s detected!");
+  AUTO_STRING (separator, ", ");
+  CALLN (Fmessage,
+         format, file,
+         Fmapconcat (Qstring,
+                     Fsort (Vlread_unescaped_character_literals, Qlss),
+                     separator));
+}
+
 DEFUN ("get-load-suffixes", Fget_load_suffixes, Sget_load_suffixes, 0, 0, 0,
        doc: /* Return the suffixes that `load' should try if a suffix is \
 required.
@@ -1202,6 +1217,11 @@ Return t if the file exists and loads successfully.  */)
   specbind (Qold_style_backquotes, Qnil);
   record_unwind_protect (load_warn_old_style_backquotes, file);
 
+  /* Check for the presence of unescaped character literals and warn
+     about them. */
+  specbind (Qlread_unescaped_character_literals, Qnil);
+  record_unwind_protect (load_warn_unescaped_character_literals, file);
+
   int is_elc;
   if ((is_elc = suffix_p (found, ".elc")) != 0
       /* version = 1 means the file is empty, in which case we can
@@ -3092,6 +3112,16 @@ read1 (Lisp_Object readcharfun, int *pch, bool 
first_in_list)
        if (c == ' ' || c == '\t')
          return make_number (c);
 
+       if (c == '(' || c == ')' || c == '[' || c == ']'
+            || c == '"' || c == ';')
+         {
+            CHECK_LIST (Vlread_unescaped_character_literals);
+            Lisp_Object char_obj = make_natnum (c);
+            if (NILP (Fmemq (char_obj, Vlread_unescaped_character_literals)))
+              Vlread_unescaped_character_literals =
+                Fcons (char_obj, Vlread_unescaped_character_literals);
+         }
+
        if (c == '\\')
          c = read_escape (readcharfun, 0);
        modifiers = c & CHAR_MODIFIER_MASK;
@@ -4815,6 +4845,16 @@ variables, this must be set in the first line of a file. 
 */);
   Vold_style_backquotes = Qnil;
   DEFSYM (Qold_style_backquotes, "old-style-backquotes");
 
+  DEFVAR_LISP ("lread--unescaped-character-literals",
+               Vlread_unescaped_character_literals,
+               doc: /* List of deprecated unescaped character literals 
encountered by `read'.
+For internal use only.  */);
+  Vlread_unescaped_character_literals = Qnil;
+  DEFSYM (Qlread_unescaped_character_literals,
+          "lread--unescaped-character-literals");
+
+  DEFSYM (Qlss, "<");
+
   DEFVAR_BOOL ("load-prefer-newer", load_prefer_newer,
                doc: /* Non-nil means `load' prefers the newest version of a 
file.
 This applies when a filename suffix is not explicitly specified and
diff --git a/test/lisp/emacs-lisp/bytecomp-tests.el 
b/test/lisp/emacs-lisp/bytecomp-tests.el
index e8feec3..3624904 100644
--- a/test/lisp/emacs-lisp/bytecomp-tests.el
+++ b/test/lisp/emacs-lisp/bytecomp-tests.el
@@ -506,6 +506,29 @@ bytecompiled code, and their results compared.")
   (dolist (pat bytecomp-lexbind-tests)
     (should (bytecomp-lexbind-check-1 pat))))
 
+(defmacro bytecomp-tests--with-temp-file (file-name-var &rest body)
+  (declare (indent 1))
+  (cl-check-type file-name-var symbol)
+  `(let ((,file-name-var (make-temp-file "emacs")))
+     (unwind-protect
+         (progn ,@body)
+       (delete-file ,file-name-var))))
+
+(ert-deftest bytecomp-tests--unescaped-char-literals ()
+  "Check that byte compiling warns about unescaped character
+literals (Bug#20852)."
+  (should (boundp 'lread--unescaped-character-literals))
+  (bytecomp-tests--with-temp-file source
+    (write-region "(list ?) ?( ?; ?\" ?[ ?])" nil source)
+    (bytecomp-tests--with-temp-file destination
+      (let* ((byte-compile-dest-file-function (lambda (_) destination))
+            (byte-compile-error-on-warn t)
+            (byte-compile-debug t)
+            (err (should-error (byte-compile-file source))))
+        (should (equal (cdr err)
+                       (list (concat "unescaped character literals "
+                                     "\", (, ), ;, [, ] detected!"))))))))
+
 ;; Local Variables:
 ;; no-byte-compile: t
 ;; End:
diff --git a/test/src/lread-tests.el b/test/src/lread-tests.el
index 27f967f..8434234 100644
--- a/test/src/lread-tests.el
+++ b/test/src/lread-tests.el
@@ -116,4 +116,30 @@
   (should (equal '(#s(foo) #s(foo))
                  (read "(#1=#s(foo) #1#)"))))
 
+(defmacro lread-tests--with-temp-file (file-name-var &rest body)
+  (declare (indent 1))
+  (cl-check-type file-name-var symbol)
+  `(let ((,file-name-var (make-temp-file "emacs")))
+     (unwind-protect
+         (progn ,@body)
+       (delete-file ,file-name-var))))
+
+(defun lread-tests--last-message ()
+  (with-current-buffer "*Messages*"
+    (save-excursion
+      (goto-char (point-max))
+      (skip-chars-backward "\n")
+      (buffer-substring (line-beginning-position) (point)))))
+
+(ert-deftest lread-tests--unescaped-char-literals ()
+  "Check that loading warns about unescaped character
+literals (Bug#20852)."
+  (lread-tests--with-temp-file file-name
+    (write-region "?) ?( ?; ?\" ?[ ?]" nil file-name)
+    (should (equal (load file-name nil :nomessage :nosuffix) t))
+    (should (equal (lread-tests--last-message)
+                   (concat (format-message "Loading `%s': " file-name)
+                           "unescaped character literals "
+                           "\", (, ), ;, [, ] detected!")))))
+
 ;;; lread-tests.el ends here



reply via email to

[Prev in Thread] Current Thread [Next in Thread]