aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp Stephani2015-06-30 22:38:35 +0200
committerPhilipp Stephani2017-05-01 20:39:10 +0200
commitc2bbdc3316487e34eba1470dd059c0c290431e00 (patch)
treebed5315e69d89c99c62be4a78e8f26d799643f70
parentb72e36047c9a5d46b02e12252e0fc640b6839903 (diff)
downloademacs-c2bbdc3316487e34eba1470dd059c0c290431e00.tar.gz
emacs-c2bbdc3316487e34eba1470dd059c0c290431e00.zip
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.
-rw-r--r--lisp/emacs-lisp/bytecomp.el7
-rw-r--r--src/lread.c40
-rw-r--r--test/lisp/emacs-lisp/bytecomp-tests.el23
-rw-r--r--test/src/lread-tests.el26
4 files changed, 96 insertions, 0 deletions
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index 15dc24060aa..25102548a9d 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."
2027 (setq byte-compile-read-position (point) 2027 (setq byte-compile-read-position (point)
2028 byte-compile-last-position byte-compile-read-position) 2028 byte-compile-last-position byte-compile-read-position)
2029 (let* ((old-style-backquotes nil) 2029 (let* ((old-style-backquotes nil)
2030 (lread--unescaped-character-literals nil)
2030 (form (read inbuffer))) 2031 (form (read inbuffer)))
2031 ;; Warn about the use of old-style backquotes. 2032 ;; Warn about the use of old-style backquotes.
2032 (when old-style-backquotes 2033 (when old-style-backquotes
2033 (byte-compile-warn "!! The file uses old-style backquotes !! 2034 (byte-compile-warn "!! The file uses old-style backquotes !!
2034This functionality has been obsolete for more than 10 years already 2035This functionality has been obsolete for more than 10 years already
2035and will be removed soon. See (elisp)Backquote in the manual.")) 2036and will be removed soon. See (elisp)Backquote in the manual."))
2037 (when lread--unescaped-character-literals
2038 (byte-compile-warn
2039 "unescaped character literals %s detected!"
2040 (mapconcat #'string
2041 (sort lread--unescaped-character-literals #'<)
2042 ", ")))
2036 (byte-compile-toplevel-file-form form))) 2043 (byte-compile-toplevel-file-form form)))
2037 ;; Compile pending forms at end of file. 2044 ;; Compile pending forms at end of file.
2038 (byte-compile-flush-pending) 2045 (byte-compile-flush-pending)
diff --git a/src/lread.c b/src/lread.c
index 3b2e123dd39..6467043b1da 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -955,6 +955,21 @@ load_warn_old_style_backquotes (Lisp_Object file)
955 } 955 }
956} 956}
957 957
958static void
959load_warn_unescaped_character_literals (Lisp_Object file)
960{
961 if (NILP (Vlread_unescaped_character_literals)) return;
962 CHECK_CONS (Vlread_unescaped_character_literals);
963 AUTO_STRING (format,
964 "Loading `%s': unescaped character literals %s detected!");
965 AUTO_STRING (separator, ", ");
966 CALLN (Fmessage,
967 format, file,
968 Fmapconcat (Qstring,
969 Fsort (Vlread_unescaped_character_literals, Qlss),
970 separator));
971}
972
958DEFUN ("get-load-suffixes", Fget_load_suffixes, Sget_load_suffixes, 0, 0, 0, 973DEFUN ("get-load-suffixes", Fget_load_suffixes, Sget_load_suffixes, 0, 0, 0,
959 doc: /* Return the suffixes that `load' should try if a suffix is \ 974 doc: /* Return the suffixes that `load' should try if a suffix is \
960required. 975required.
@@ -1202,6 +1217,11 @@ Return t if the file exists and loads successfully. */)
1202 specbind (Qold_style_backquotes, Qnil); 1217 specbind (Qold_style_backquotes, Qnil);
1203 record_unwind_protect (load_warn_old_style_backquotes, file); 1218 record_unwind_protect (load_warn_old_style_backquotes, file);
1204 1219
1220 /* Check for the presence of unescaped character literals and warn
1221 about them. */
1222 specbind (Qlread_unescaped_character_literals, Qnil);
1223 record_unwind_protect (load_warn_unescaped_character_literals, file);
1224
1205 int is_elc; 1225 int is_elc;
1206 if ((is_elc = suffix_p (found, ".elc")) != 0 1226 if ((is_elc = suffix_p (found, ".elc")) != 0
1207 /* version = 1 means the file is empty, in which case we can 1227 /* 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)
3092 if (c == ' ' || c == '\t') 3112 if (c == ' ' || c == '\t')
3093 return make_number (c); 3113 return make_number (c);
3094 3114
3115 if (c == '(' || c == ')' || c == '[' || c == ']'
3116 || c == '"' || c == ';')
3117 {
3118 CHECK_LIST (Vlread_unescaped_character_literals);
3119 Lisp_Object char_obj = make_natnum (c);
3120 if (NILP (Fmemq (char_obj, Vlread_unescaped_character_literals)))
3121 Vlread_unescaped_character_literals =
3122 Fcons (char_obj, Vlread_unescaped_character_literals);
3123 }
3124
3095 if (c == '\\') 3125 if (c == '\\')
3096 c = read_escape (readcharfun, 0); 3126 c = read_escape (readcharfun, 0);
3097 modifiers = c & CHAR_MODIFIER_MASK; 3127 modifiers = c & CHAR_MODIFIER_MASK;
@@ -4815,6 +4845,16 @@ variables, this must be set in the first line of a file. */);
4815 Vold_style_backquotes = Qnil; 4845 Vold_style_backquotes = Qnil;
4816 DEFSYM (Qold_style_backquotes, "old-style-backquotes"); 4846 DEFSYM (Qold_style_backquotes, "old-style-backquotes");
4817 4847
4848 DEFVAR_LISP ("lread--unescaped-character-literals",
4849 Vlread_unescaped_character_literals,
4850 doc: /* List of deprecated unescaped character literals encountered by `read'.
4851For internal use only. */);
4852 Vlread_unescaped_character_literals = Qnil;
4853 DEFSYM (Qlread_unescaped_character_literals,
4854 "lread--unescaped-character-literals");
4855
4856 DEFSYM (Qlss, "<");
4857
4818 DEFVAR_BOOL ("load-prefer-newer", load_prefer_newer, 4858 DEFVAR_BOOL ("load-prefer-newer", load_prefer_newer,
4819 doc: /* Non-nil means `load' prefers the newest version of a file. 4859 doc: /* Non-nil means `load' prefers the newest version of a file.
4820This applies when a filename suffix is not explicitly specified and 4860This 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 e8feec31d26..3624904753c 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.")
506 (dolist (pat bytecomp-lexbind-tests) 506 (dolist (pat bytecomp-lexbind-tests)
507 (should (bytecomp-lexbind-check-1 pat)))) 507 (should (bytecomp-lexbind-check-1 pat))))
508 508
509(defmacro bytecomp-tests--with-temp-file (file-name-var &rest body)
510 (declare (indent 1))
511 (cl-check-type file-name-var symbol)
512 `(let ((,file-name-var (make-temp-file "emacs")))
513 (unwind-protect
514 (progn ,@body)
515 (delete-file ,file-name-var))))
516
517(ert-deftest bytecomp-tests--unescaped-char-literals ()
518 "Check that byte compiling warns about unescaped character
519literals (Bug#20852)."
520 (should (boundp 'lread--unescaped-character-literals))
521 (bytecomp-tests--with-temp-file source
522 (write-region "(list ?) ?( ?; ?\" ?[ ?])" nil source)
523 (bytecomp-tests--with-temp-file destination
524 (let* ((byte-compile-dest-file-function (lambda (_) destination))
525 (byte-compile-error-on-warn t)
526 (byte-compile-debug t)
527 (err (should-error (byte-compile-file source))))
528 (should (equal (cdr err)
529 (list (concat "unescaped character literals "
530 "\", (, ), ;, [, ] detected!"))))))))
531
509;; Local Variables: 532;; Local Variables:
510;; no-byte-compile: t 533;; no-byte-compile: t
511;; End: 534;; End:
diff --git a/test/src/lread-tests.el b/test/src/lread-tests.el
index 27f967f045b..84342348d45 100644
--- a/test/src/lread-tests.el
+++ b/test/src/lread-tests.el
@@ -116,4 +116,30 @@
116 (should (equal '(#s(foo) #s(foo)) 116 (should (equal '(#s(foo) #s(foo))
117 (read "(#1=#s(foo) #1#)")))) 117 (read "(#1=#s(foo) #1#)"))))
118 118
119(defmacro lread-tests--with-temp-file (file-name-var &rest body)
120 (declare (indent 1))
121 (cl-check-type file-name-var symbol)
122 `(let ((,file-name-var (make-temp-file "emacs")))
123 (unwind-protect
124 (progn ,@body)
125 (delete-file ,file-name-var))))
126
127(defun lread-tests--last-message ()
128 (with-current-buffer "*Messages*"
129 (save-excursion
130 (goto-char (point-max))
131 (skip-chars-backward "\n")
132 (buffer-substring (line-beginning-position) (point)))))
133
134(ert-deftest lread-tests--unescaped-char-literals ()
135 "Check that loading warns about unescaped character
136literals (Bug#20852)."
137 (lread-tests--with-temp-file file-name
138 (write-region "?) ?( ?; ?\" ?[ ?]" nil file-name)
139 (should (equal (load file-name nil :nomessage :nosuffix) t))
140 (should (equal (lread-tests--last-message)
141 (concat (format-message "Loading `%s': " file-name)
142 "unescaped character literals "
143 "\", (, ), ;, [, ] detected!")))))
144
119;;; lread-tests.el ends here 145;;; lread-tests.el ends here