aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Kangas2020-12-06 12:44:19 +0100
committerStefan Kangas2020-12-28 06:26:52 +0100
commit0ebea8ffbfb7b9b1bd92f30011df0875b54eb663 (patch)
tree1160c96525469cf2be56f18448ec485e8b50a531
parented30956099fff5025698c8ffdd9e876f207ed2af (diff)
downloademacs-0ebea8ffbfb7b9b1bd92f30011df0875b54eb663.tar.gz
emacs-0ebea8ffbfb7b9b1bd92f30011df0875b54eb663.zip
Make byte-compiler warn about wide docstrings
* lisp/emacs-lisp/bytecomp.el (byte-compile--wide-docstring-p): (byte-compile-docstring-length-warn): New defuns. (byte-compile-docstring-max-column): New defcustom. (byte-compile--wide-docstring-substitution-len): New variable. (byte-compile-warning-types, byte-compile-warnings): New value 'docstrings'. (byte-compile-file-form-autoload, byte-compile-file-form-defvar): (byte-compile-file-form-defvar-function, byte-compile-lambda): (byte-compile-defvar, byte-compile-file-form-defalias): Warn about too wide docstrings. (Bug#44858) * test/lisp/emacs-lisp/bytecomp-tests.el (bytecomp-warn-wide-docstring/defconst) (bytecomp-warn-wide-docstring/defvar): New tests. (bytecomp--define-warning-file-test): New macro. (bytecomp/warn-wide-docstring-autoload\.el) (bytecomp/warn-wide-docstring-custom-declare-variable\.el) (bytecomp/warn-wide-docstring-defalias\.el) (bytecomp/warn-wide-docstring-defconst\.el) (bytecomp/warn-wide-docstring-define-abbrev-table\.el) (bytecomp/warn-wide-docstring-define-obsolete-function-alias\.el) (bytecomp/warn-wide-docstring-define-obsolete-variable-alias\.el) (bytecomp/warn-wide-docstring-defun\.el) (bytecomp/warn-wide-docstring-defvar\.el) (bytecomp/warn-wide-docstring-defvaralias\.el) (bytecomp/warn-wide-docstring-ignore-fill-column\.el) (bytecomp/warn-wide-docstring-ignore-override\.el) (bytecomp/warn-wide-docstring-ignore\.el) (bytecomp/warn-wide-docstring-multiline-first\.el) (bytecomp/warn-wide-docstring-multiline\.el): New tests. * test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-autoload.el: * test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-custom-declare-variable.el: * test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defalias.el: * test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defconst.el: * test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-define-abbrev-table.el: * test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-define-obsolete-function-alias.el: * test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-define-obsolete-variable-alias.el: * test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defun.el: * test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defvar.el: * test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defvaralias.el: * test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-ignore-fill-column.el: * test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-ignore-override.el: * test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-ignore.el: * test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-multiline-first.el: * test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-multiline.el: New files.
-rw-r--r--etc/NEWS11
-rw-r--r--etc/TODO2
-rw-r--r--lisp/emacs-lisp/bytecomp.el88
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-autoload.el3
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-custom-declare-variable.el4
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defalias.el3
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defconst.el3
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-define-abbrev-table.el3
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-define-obsolete-function-alias.el3
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-define-obsolete-variable-alias.el3
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defun.el3
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defvar.el6
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defvaralias.el3
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-ignore-fill-column.el7
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-ignore-override.el8
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-ignore.el7
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-multiline-first.el5
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-multiline.el6
-rw-r--r--test/lisp/emacs-lisp/bytecomp-tests.el71
19 files changed, 233 insertions, 6 deletions
diff --git a/etc/NEWS b/etc/NEWS
index 131931052a5..f8282696e46 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -2200,17 +2200,24 @@ menu handling.
2200+++ 2200+++
2201** 'inhibit-nul-byte-detection' is renamed to 'inhibit-null-byte-detection'. 2201** 'inhibit-nul-byte-detection' is renamed to 'inhibit-null-byte-detection'.
2202 2202
2203** Byte compiler
2204
2203+++ 2205+++
2204** New byte-compiler check for missing dynamic variable declarations. 2206*** New byte-compiler check for missing dynamic variable declarations.
2205It is meant as an (experimental) aid for converting Emacs Lisp code 2207It is meant as an (experimental) aid for converting Emacs Lisp code
2206to lexical binding, where dynamic (special) variables bound in one 2208to lexical binding, where dynamic (special) variables bound in one
2207file can affect code in another. For details, see the manual section 2209file can affect code in another. For details, see the manual section
2208"(Elisp) Converting to Lexical Binding". 2210"(Elisp) Converting to Lexical Binding".
2209 2211
2210+++ 2212+++
2211** 'byte-recompile-directory' can now compile symlinked ".el" files. 2213*** 'byte-recompile-directory' can now compile symlinked ".el" files.
2212This is achieved by giving a non-nil FOLLOW-SYMLINKS parameter. 2214This is achieved by giving a non-nil FOLLOW-SYMLINKS parameter.
2213 2215
2216*** The byte-compiler now warns about too wide documentation strings.
2217By default, it will warn if a documentation string is wider than the
2218largest of 80 characters or 'fill-column'. This is controlled by the
2219new user option 'byte-compile-docstring-max-column'.
2220
2214--- 2221---
2215** 'unload-feature' now also tries to undo additions to buffer-local hooks. 2222** 'unload-feature' now also tries to undo additions to buffer-local hooks.
2216 2223
diff --git a/etc/TODO b/etc/TODO
index 2a9fd8869e0..d7bcfd4d97c 100644
--- a/etc/TODO
+++ b/etc/TODO
@@ -638,8 +638,6 @@ Do this for some or all errors associated with using subprocesses.
638** Maybe reinterpret 'parse-error' as a category of errors 638** Maybe reinterpret 'parse-error' as a category of errors
639Put some other errors under it. 639Put some other errors under it.
640 640
641** Make byte-compiler warn when a doc string is too wide
642
643** Make byte-optimization warnings issue accurate line numbers 641** Make byte-optimization warnings issue accurate line numbers
644 642
645** Record the sxhash of the default value for customized variables 643** Record the sxhash of the default value for customized variables
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index 7e1a3304cc8..f14ad93d2e0 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -299,7 +299,8 @@ The information is logged to `byte-compile-log-buffer'."
299(defconst byte-compile-warning-types 299(defconst byte-compile-warning-types
300 '(redefine callargs free-vars unresolved 300 '(redefine callargs free-vars unresolved
301 obsolete noruntime interactive-only 301 obsolete noruntime interactive-only
302 make-local mapcar constants suspicious lexical lexical-dynamic) 302 make-local mapcar constants suspicious lexical lexical-dynamic
303 docstrings)
303 "The list of warning types used when `byte-compile-warnings' is t.") 304 "The list of warning types used when `byte-compile-warnings' is t.")
304(defcustom byte-compile-warnings t 305(defcustom byte-compile-warnings t
305 "List of warnings that the byte-compiler should issue (t for all). 306 "List of warnings that the byte-compiler should issue (t for all).
@@ -322,6 +323,8 @@ Elements of the list may be:
322 make-local calls to make-variable-buffer-local that may be incorrect. 323 make-local calls to make-variable-buffer-local that may be incorrect.
323 mapcar mapcar called for effect. 324 mapcar mapcar called for effect.
324 constants let-binding of, or assignment to, constants/nonvariables. 325 constants let-binding of, or assignment to, constants/nonvariables.
326 docstrings docstrings that are too wide (longer than 80 characters,
327 or `fill-column', whichever is bigger)
325 suspicious constructs that usually don't do what the coder wanted. 328 suspicious constructs that usually don't do what the coder wanted.
326 329
327If the list begins with `not', then the remaining elements specify warnings to 330If the list begins with `not', then the remaining elements specify warnings to
@@ -1563,6 +1566,81 @@ extra args."
1563 (if (equal sig1 '(1 . 1)) "argument" "arguments") 1566 (if (equal sig1 '(1 . 1)) "argument" "arguments")
1564 (byte-compile-arglist-signature-string sig2))))))) 1567 (byte-compile-arglist-signature-string sig2)))))))
1565 1568
1569(defvar byte-compile--wide-docstring-substitution-len 3
1570 "Substitution width used in `byte-compile--wide-docstring-p'.
1571This is a heuristic for guessing the width of a documentation
1572string: `byte-compile--wide-docstring-p' assumes that any
1573`substitute-command-keys' command substitutions are this long.")
1574
1575(defun byte-compile--wide-docstring-p (docstring col)
1576 "Return t if string DOCSTRING is wider than COL.
1577Ignore all `substitute-command-keys' substitutions, except for
1578the `\\\\=[command]' ones that are assumed to be of length
1579`byte-compile--wide-docstring-substitution-len'. Also ignore
1580URLs."
1581 (string-match
1582 (format "^.\\{%s,\\}$" (int-to-string (1+ col)))
1583 (replace-regexp-in-string
1584 (rx (or
1585 ;; Ignore some URLs.
1586 (seq "http" (? "s") "://" (* anychar))
1587 ;; Ignore these `substitute-command-keys' substitutions.
1588 (seq "\\" (or "="
1589 (seq "<" (* (not ">")) ">")
1590 (seq "{" (* (not "}")) "}")))))
1591 ""
1592 ;; Heuristic: assume these substitutions are of some length N.
1593 (replace-regexp-in-string
1594 (rx "\\" (or (seq "[" (* (not "]")) "]")))
1595 (make-string byte-compile--wide-docstring-substitution-len ?x)
1596 docstring))))
1597
1598(defcustom byte-compile-docstring-max-column 80
1599 "Recommended maximum width of doc string lines.
1600The byte-compiler will emit a warning for documentation strings
1601containing lines wider than this. If `fill-column' has a larger
1602value, it will override this variable."
1603 :group 'bytecomp
1604 :type 'integer
1605 :safe #'integerp
1606 :version "28.1")
1607
1608(defun byte-compile-docstring-length-warn (form)
1609 "Warn if documentation string of FORM is too wide.
1610It is too wide if it has any lines longer than the largest of
1611`fill-column' and `byte-compile-docstring-max-column'."
1612 ;; This has some limitations that it would be nice to fix:
1613 ;; 1. We don't try to handle defuns. It is somewhat tricky to get
1614 ;; it right since `defun' is a macro. Also, some macros
1615 ;; themselves produce defuns (e.g. `define-derived-mode').
1616 ;; 2. We assume that any `subsititute-command-keys' command replacement has a
1617 ;; given length. We can't reliably do these replacements, since the value
1618 ;; of the keymaps in general can't be known at compile time.
1619 (when (byte-compile-warning-enabled-p 'docstrings)
1620 (let ((col (max byte-compile-docstring-max-column fill-column))
1621 kind name docs)
1622 (pcase (car form)
1623 ((or 'autoload 'custom-declare-variable 'defalias
1624 'defconst 'define-abbrev-table
1625 'defvar 'defvaralias)
1626 (setq kind (nth 0 form))
1627 (setq name (nth 1 form))
1628 (setq docs (nth 3 form)))
1629 ;; Here is how one could add lambda's here:
1630 ;; ('lambda
1631 ;; (setq kind "") ; can't be "function", unfortunately
1632 ;; (setq docs (and (stringp (nth 2 form))
1633 ;; (nth 2 form))))
1634 )
1635 (when (and (consp name) (eq (car name) 'quote))
1636 (setq name (cadr name)))
1637 (setq name (if name (format " `%s'" name) ""))
1638 (when (and kind docs (stringp docs)
1639 (byte-compile--wide-docstring-p docs col))
1640 (byte-compile-warn "%s%s docstring wider than %s characters"
1641 kind name col))))
1642 form)
1643
1566(defun byte-compile-print-syms (str1 strn syms) 1644(defun byte-compile-print-syms (str1 strn syms)
1567 (when syms 1645 (when syms
1568 (byte-compile-set-symbol-position (car syms) t)) 1646 (byte-compile-set-symbol-position (car syms) t))
@@ -2410,7 +2488,8 @@ list that represents a doc string reference.
2410 (delq (assq funsym byte-compile-unresolved-functions) 2488 (delq (assq funsym byte-compile-unresolved-functions)
2411 byte-compile-unresolved-functions))))) 2489 byte-compile-unresolved-functions)))))
2412 (if (stringp (nth 3 form)) 2490 (if (stringp (nth 3 form))
2413 form 2491 (prog1 form
2492 (byte-compile-docstring-length-warn form))
2414 ;; No doc string, so we can compile this as a normal form. 2493 ;; No doc string, so we can compile this as a normal form.
2415 (byte-compile-keep-pending form 'byte-compile-normal-call))) 2494 (byte-compile-keep-pending form 'byte-compile-normal-call)))
2416 2495
@@ -2438,6 +2517,7 @@ list that represents a doc string reference.
2438 (if (and (null (cddr form)) ;No `value' provided. 2517 (if (and (null (cddr form)) ;No `value' provided.
2439 (eq (car form) 'defvar)) ;Just a declaration. 2518 (eq (car form) 'defvar)) ;Just a declaration.
2440 nil 2519 nil
2520 (byte-compile-docstring-length-warn form)
2441 (cond ((consp (nth 2 form)) 2521 (cond ((consp (nth 2 form))
2442 (setq form (copy-sequence form)) 2522 (setq form (copy-sequence form))
2443 (setcar (cdr (cdr form)) 2523 (setcar (cdr (cdr form))
@@ -2461,6 +2541,7 @@ list that represents a doc string reference.
2461 (if (byte-compile-warning-enabled-p 'suspicious) 2541 (if (byte-compile-warning-enabled-p 'suspicious)
2462 (byte-compile-warn 2542 (byte-compile-warn
2463 "Alias for `%S' should be declared before its referent" newname))))) 2543 "Alias for `%S' should be declared before its referent" newname)))))
2544 (byte-compile-docstring-length-warn form)
2464 (byte-compile-keep-pending form)) 2545 (byte-compile-keep-pending form))
2465 2546
2466(put 'custom-declare-variable 'byte-hunk-handler 2547(put 'custom-declare-variable 'byte-hunk-handler
@@ -2844,6 +2925,7 @@ for symbols generated by the byte compiler itself."
2844 (unless (eq 'lambda (car-safe fun)) 2925 (unless (eq 'lambda (car-safe fun))
2845 (error "Not a lambda list: %S" fun)) 2926 (error "Not a lambda list: %S" fun))
2846 (byte-compile-set-symbol-position 'lambda)) 2927 (byte-compile-set-symbol-position 'lambda))
2928 (byte-compile-docstring-length-warn fun)
2847 (byte-compile-check-lambda-list (nth 1 fun)) 2929 (byte-compile-check-lambda-list (nth 1 fun))
2848 (let* ((arglist (nth 1 fun)) 2930 (let* ((arglist (nth 1 fun))
2849 (arglistvars (byte-compile-arglist-vars arglist)) 2931 (arglistvars (byte-compile-arglist-vars arglist))
@@ -4624,6 +4706,7 @@ binding slots have been popped."
4624 (byte-compile-warning-enabled-p 'lexical (nth 1 form))) 4706 (byte-compile-warning-enabled-p 'lexical (nth 1 form)))
4625 (byte-compile-warn "global/dynamic var `%s' lacks a prefix" 4707 (byte-compile-warn "global/dynamic var `%s' lacks a prefix"
4626 (nth 1 form))) 4708 (nth 1 form)))
4709 (byte-compile-docstring-length-warn form)
4627 (let ((fun (nth 0 form)) 4710 (let ((fun (nth 0 form))
4628 (var (nth 1 form)) 4711 (var (nth 1 form))
4629 (value (nth 2 form)) 4712 (value (nth 2 form))
@@ -4698,6 +4781,7 @@ binding slots have been popped."
4698 ;; - `arg' is the expression to which it is defined. 4781 ;; - `arg' is the expression to which it is defined.
4699 ;; - `rest' is the rest of the arguments. 4782 ;; - `rest' is the rest of the arguments.
4700 (`(,_ ',name ,arg . ,rest) 4783 (`(,_ ',name ,arg . ,rest)
4784 (byte-compile-docstring-length-warn form)
4701 (pcase-let* 4785 (pcase-let*
4702 ;; `macro' is non-nil if it defines a macro. 4786 ;; `macro' is non-nil if it defines a macro.
4703 ;; `fun' is the function part of `arg' (defaults to `arg'). 4787 ;; `fun' is the function part of `arg' (defaults to `arg').
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-autoload.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-autoload.el
new file mode 100644
index 00000000000..96deb1bbb0a
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-autoload.el
@@ -0,0 +1,3 @@
1;;; -*- lexical-binding: t -*-
2(autoload 'foox "foo"
3 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-custom-declare-variable.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-custom-declare-variable.el
new file mode 100644
index 00000000000..2a4700bfda5
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-custom-declare-variable.el
@@ -0,0 +1,4 @@
1;;; -*- lexical-binding: t -*-
2(custom-declare-variable
3 'foo t
4 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defalias.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defalias.el
new file mode 100644
index 00000000000..a4235d22bd3
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defalias.el
@@ -0,0 +1,3 @@
1;;; -*- lexical-binding: t -*-
2(defalias 'foo #'ignore
3 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defconst.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defconst.el
new file mode 100644
index 00000000000..946f01989a0
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defconst.el
@@ -0,0 +1,3 @@
1;;; -*- lexical-binding: t -*-
2(defconst foo-bar nil
3 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-define-abbrev-table.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-define-abbrev-table.el
new file mode 100644
index 00000000000..3da9ccd48c6
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-define-abbrev-table.el
@@ -0,0 +1,3 @@
1;;; -*- lexical-binding: t -*-
2(define-abbrev-table 'foo ()
3 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-define-obsolete-function-alias.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-define-obsolete-function-alias.el
new file mode 100644
index 00000000000..fea841b12ec
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-define-obsolete-function-alias.el
@@ -0,0 +1,3 @@
1;;; -*- lexical-binding: t -*-
2(define-obsolete-function-alias 'foo #'ignore "99.1"
3 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-define-obsolete-variable-alias.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-define-obsolete-variable-alias.el
new file mode 100644
index 00000000000..2d5f201cb65
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-define-obsolete-variable-alias.el
@@ -0,0 +1,3 @@
1;;; -*- lexical-binding: t -*-
2(define-obsolete-variable-alias 'foo 'ignore "99.1"
3 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defun.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defun.el
new file mode 100644
index 00000000000..94b0e80c979
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defun.el
@@ -0,0 +1,3 @@
1;;; -*- lexical-binding: t -*-
2(defun foo ()
3 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defvar.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defvar.el
new file mode 100644
index 00000000000..99aacd09cbd
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defvar.el
@@ -0,0 +1,6 @@
1;;; -*- lexical-binding: t -*-
2(defvar foo-bar nil
3 "multiline
4foo
5xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
6bar")
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defvaralias.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defvaralias.el
new file mode 100644
index 00000000000..52fdc17f5bf
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-defvaralias.el
@@ -0,0 +1,3 @@
1;;; -*- lexical-binding: t -*-
2(defvaralias 'foo-bar #'ignore
3 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-ignore-fill-column.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-ignore-fill-column.el
new file mode 100644
index 00000000000..1ff554f3704
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-ignore-fill-column.el
@@ -0,0 +1,7 @@
1;;; -*- lexical-binding: t -*-
2(defvar foo-bar nil
3 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
4
5;; Local Variables:
6;; fill-column: 100
7;; End:
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-ignore-override.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-ignore-override.el
new file mode 100644
index 00000000000..0bcf7b1d63b
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-ignore-override.el
@@ -0,0 +1,8 @@
1;;; -*- lexical-binding: t -*-
2(defvar foo-bar nil
3 "123456789012345")
4
5;; Local Variables:
6;; byte-compile-docstring-max-column: 10
7;; fill-column: 20
8;; End:
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-ignore.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-ignore.el
new file mode 100644
index 00000000000..c80ddd180d9
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-ignore.el
@@ -0,0 +1,7 @@
1;;; -*- lexical-binding: t -*-
2(defvar foo-bar nil
3 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
4
5;; Local Variables:
6;; byte-compile-docstring-max-column: 100
7;; End:
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-multiline-first.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-multiline-first.el
new file mode 100644
index 00000000000..2563dbbb3b9
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-multiline-first.el
@@ -0,0 +1,5 @@
1;;; -*- lexical-binding: t -*-
2(defvar foo-bar nil
3 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
4This is a multiline docstring where the first line is long.
5foobar")
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-multiline.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-multiline.el
new file mode 100644
index 00000000000..9ae7bc9b9f0
--- /dev/null
+++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-wide-docstring-multiline.el
@@ -0,0 +1,6 @@
1;;; -*- lexical-binding: t -*-
2(defvar foo-bar nil
3 "This is a multiline docstring.
4But it's not the first line that is long.
5xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
6foobar")
diff --git a/test/lisp/emacs-lisp/bytecomp-tests.el b/test/lisp/emacs-lisp/bytecomp-tests.el
index 4a6e28f7c7c..47aab563f6f 100644
--- a/test/lisp/emacs-lisp/bytecomp-tests.el
+++ b/test/lisp/emacs-lisp/bytecomp-tests.el
@@ -540,6 +540,16 @@ Subtests signal errors if something goes wrong."
540 (bytecomp--with-warning-test "foo.*lacks a prefix" 540 (bytecomp--with-warning-test "foo.*lacks a prefix"
541 '(defvar foo nil))) 541 '(defvar foo nil)))
542 542
543(defvar bytecomp-tests--docstring (make-string 100 ?x))
544
545(ert-deftest bytecomp-warn-wide-docstring/defconst ()
546 (bytecomp--with-warning-test "defconst.*foo.*wider than.*characters"
547 `(defconst foo t ,bytecomp-tests--docstring)))
548
549(ert-deftest bytecomp-warn-wide-docstring/defvar ()
550 (bytecomp--with-warning-test "defvar.*foo.*wider than.*characters"
551 `(defvar foo t ,bytecomp-tests--docstring)))
552
543(defmacro bytecomp--define-warning-file-test (file re-warning &optional reverse) 553(defmacro bytecomp--define-warning-file-test (file re-warning &optional reverse)
544 `(ert-deftest ,(intern (format "bytecomp/%s" file)) () 554 `(ert-deftest ,(intern (format "bytecomp/%s" file)) ()
545 :expected-result ,(if reverse :failed :passed) 555 :expected-result ,(if reverse :failed :passed)
@@ -639,6 +649,67 @@ Subtests signal errors if something goes wrong."
639(bytecomp--define-warning-file-test "warn-variable-set-nonvariable.el" 649(bytecomp--define-warning-file-test "warn-variable-set-nonvariable.el"
640 "variable reference to nonvariable") 650 "variable reference to nonvariable")
641 651
652(bytecomp--define-warning-file-test
653 "warn-wide-docstring-autoload.el"
654 "autoload.*foox.*wider than.*characters")
655
656(bytecomp--define-warning-file-test
657 "warn-wide-docstring-custom-declare-variable.el"
658 "custom-declare-variable.*foo.*wider than.*characters")
659
660(bytecomp--define-warning-file-test
661 "warn-wide-docstring-defalias.el"
662 "defalias.*foo.*wider than.*characters")
663
664(bytecomp--define-warning-file-test
665 "warn-wide-docstring-defconst.el"
666 "defconst.*foo.*wider than.*characters")
667
668(bytecomp--define-warning-file-test
669 "warn-wide-docstring-define-abbrev-table.el"
670 "define-abbrev.*foo.*wider than.*characters")
671
672(bytecomp--define-warning-file-test
673 "warn-wide-docstring-define-obsolete-function-alias.el"
674 "defalias.*foo.*wider than.*characters")
675
676(bytecomp--define-warning-file-test
677 "warn-wide-docstring-define-obsolete-variable-alias.el"
678 "defvaralias.*foo.*wider than.*characters")
679
680;; TODO: We don't yet issue warnings for defuns.
681(bytecomp--define-warning-file-test
682 "warn-wide-docstring-defun.el"
683 "wider than.*characters" 'reverse)
684
685(bytecomp--define-warning-file-test
686 "warn-wide-docstring-defvar.el"
687 "defvar.*foo.*wider than.*characters")
688
689(bytecomp--define-warning-file-test
690 "warn-wide-docstring-defvaralias.el"
691 "defvaralias.*foo.*wider than.*characters")
692
693(bytecomp--define-warning-file-test
694 "warn-wide-docstring-ignore-fill-column.el"
695 "defvar.*foo.*wider than.*characters" 'reverse)
696
697(bytecomp--define-warning-file-test
698 "warn-wide-docstring-ignore-override.el"
699 "defvar.*foo.*wider than.*characters" 'reverse)
700
701(bytecomp--define-warning-file-test
702 "warn-wide-docstring-ignore.el"
703 "defvar.*foo.*wider than.*characters" 'reverse)
704
705(bytecomp--define-warning-file-test
706 "warn-wide-docstring-multiline-first.el"
707 "defvar.*foo.*wider than.*characters")
708
709(bytecomp--define-warning-file-test
710 "warn-wide-docstring-multiline.el"
711 "defvar.*foo.*wider than.*characters")
712
642 713
643;;;; Macro expansion. 714;;;; Macro expansion.
644 715