aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp Stephani2016-12-30 18:00:54 +0100
committerPhilipp Stephani2016-12-31 17:30:46 +0100
commit4bbd5424a2290ab4bd88c0af602b7aa7d53a407e (patch)
treec6928916fdb29df58d509e519953adc1fe21f6a3
parent8a165813cb9321a8979ac6d98530f5e4392fb879 (diff)
downloademacs-4bbd5424a2290ab4bd88c0af602b7aa7d53a407e.tar.gz
emacs-4bbd5424a2290ab4bd88c0af602b7aa7d53a407e.zip
Checkdoc: use syntax functions instead of regex
In checkdoc.el, get rid of the error-prone regex to find definition forms, and use existing syntax-based navigation functions instead. This fixes a corner case with one-argument `defvar' forms. * lisp/emacs-lisp/checkdoc.el (checkdoc--next-docstring): New function. (checkdoc-next-docstring, checkdoc-defun): Use it. * test/lisp/emacs-lisp/checkdoc-tests.el (checkdoc-tests--next-docstring): Add unit test.
-rw-r--r--lisp/emacs-lisp/checkdoc.el59
-rw-r--r--test/lisp/emacs-lisp/checkdoc-tests.el13
2 files changed, 44 insertions, 28 deletions
diff --git a/lisp/emacs-lisp/checkdoc.el b/lisp/emacs-lisp/checkdoc.el
index 2c8bc020d38..55978ddd384 100644
--- a/lisp/emacs-lisp/checkdoc.el
+++ b/lisp/emacs-lisp/checkdoc.el
@@ -294,12 +294,6 @@ problem discovered. This is useful for adding additional checks.")
294(defvar checkdoc-diagnostic-buffer "*Style Warnings*" 294(defvar checkdoc-diagnostic-buffer "*Style Warnings*"
295 "Name of warning message buffer.") 295 "Name of warning message buffer.")
296 296
297(defvar checkdoc-defun-regexp
298 "^(def\\(un\\|var\\|custom\\|macro\\|const\\|subst\\|advice\\)\
299\\s-+\\(\\(\\sw\\|\\s_\\)+\\)[ \t\n]*"
300 "Regular expression used to identify a defun.
301A search leaves the cursor in front of the parameter list.")
302
303(defcustom checkdoc-verb-check-experimental-flag t 297(defcustom checkdoc-verb-check-experimental-flag t
304 "Non-nil means to attempt to check the voice of the doc string. 298 "Non-nil means to attempt to check the voice of the doc string.
305This check keys off some words which are commonly misused. See the 299This check keys off some words which are commonly misused. See the
@@ -938,13 +932,31 @@ is the starting location. If this is nil, `point-min' is used instead."
938(defun checkdoc-next-docstring () 932(defun checkdoc-next-docstring ()
939 "Move to the next doc string after point, and return t. 933 "Move to the next doc string after point, and return t.
940Return nil if there are no more doc strings." 934Return nil if there are no more doc strings."
941 (if (not (re-search-forward checkdoc-defun-regexp nil t)) 935 (let (found)
942 nil 936 (while (and (not (setq found (checkdoc--next-docstring)))
943 ;; search drops us after the identifier. The next sexp is either 937 (beginning-of-defun -1)))
944 ;; the argument list or the value of the variable. skip it. 938 found))
945 (forward-sexp 1) 939
946 (skip-chars-forward " \n\t") 940(defun checkdoc--next-docstring ()
947 t)) 941 "When looking at a definition with a doc string, find it.
942Move to the next doc string after point, and return t. When not
943looking at a definition containing a doc string, return nil and
944don't move point."
945 (pcase (save-excursion (condition-case nil
946 (read (current-buffer))
947 ;; Conservatively skip syntax errors.
948 (invalid-read-syntax)))
949 (`(,(or 'defun 'defvar 'defcustom 'defmacro 'defconst 'defsubst 'defadvice)
950 ,(pred symbolp)
951 ;; Require an initializer, i.e. ignore single-argument `defvar'
952 ;; forms, which never have a doc string.
953 ,_ . ,_)
954 (down-list)
955 ;; Skip over function or macro name, symbol to be defined, and
956 ;; initializer or argument list.
957 (forward-sexp 3)
958 (skip-chars-forward " \n\t")
959 t)))
948 960
949;;;###autoload 961;;;###autoload
950(defun checkdoc-comments (&optional take-notes) 962(defun checkdoc-comments (&optional take-notes)
@@ -1027,21 +1039,12 @@ space at the end of each line."
1027 (interactive) 1039 (interactive)
1028 (save-excursion 1040 (save-excursion
1029 (beginning-of-defun) 1041 (beginning-of-defun)
1030 (if (not (looking-at checkdoc-defun-regexp)) 1042 (when (checkdoc--next-docstring)
1031 ;; I found this more annoying than useful.
1032 ;;(if (not no-error)
1033 ;; (message "Cannot check this sexp's doc string."))
1034 nil
1035 ;; search drops us after the identifier. The next sexp is either
1036 ;; the argument list or the value of the variable. skip it.
1037 (goto-char (match-end 0))
1038 (forward-sexp 1)
1039 (skip-chars-forward " \n\t")
1040 (let* ((checkdoc-spellcheck-documentation-flag 1043 (let* ((checkdoc-spellcheck-documentation-flag
1041 (car (memq checkdoc-spellcheck-documentation-flag 1044 (car (memq checkdoc-spellcheck-documentation-flag
1042 '(defun t)))) 1045 '(defun t))))
1043 (beg (save-excursion (beginning-of-defun) (point))) 1046 (beg (save-excursion (beginning-of-defun) (point)))
1044 (end (save-excursion (end-of-defun) (point)))) 1047 (end (save-excursion (end-of-defun) (point))))
1045 (dolist (fun (list #'checkdoc-this-string-valid 1048 (dolist (fun (list #'checkdoc-this-string-valid
1046 (lambda () (checkdoc-message-text-search beg end)) 1049 (lambda () (checkdoc-message-text-search beg end))
1047 (lambda () (checkdoc-rogue-space-check-engine beg end)))) 1050 (lambda () (checkdoc-rogue-space-check-engine beg end))))
@@ -1049,8 +1052,8 @@ space at the end of each line."
1049 (if msg (if no-error 1052 (if msg (if no-error
1050 (message "%s" (checkdoc-error-text msg)) 1053 (message "%s" (checkdoc-error-text msg))
1051 (user-error "%s" (checkdoc-error-text msg)))))) 1054 (user-error "%s" (checkdoc-error-text msg))))))
1052 (if (called-interactively-p 'interactive) 1055 (if (called-interactively-p 'interactive)
1053 (message "Checkdoc: done.")))))) 1056 (message "Checkdoc: done."))))))
1054 1057
1055;;; Ispell interface for forcing a spell check 1058;;; Ispell interface for forcing a spell check
1056;; 1059;;
diff --git a/test/lisp/emacs-lisp/checkdoc-tests.el b/test/lisp/emacs-lisp/checkdoc-tests.el
index 18b5a499e08..02db88c17e2 100644
--- a/test/lisp/emacs-lisp/checkdoc-tests.el
+++ b/test/lisp/emacs-lisp/checkdoc-tests.el
@@ -37,4 +37,17 @@
37 (insert "(defun foo())") 37 (insert "(defun foo())")
38 (should-error (checkdoc-defun) :type 'user-error))) 38 (should-error (checkdoc-defun) :type 'user-error)))
39 39
40(ert-deftest checkdoc-tests--next-docstring ()
41 "Checks that the one-argument form of `defvar' works.
42See the comments in Bug#24998."
43 (with-temp-buffer
44 (emacs-lisp-mode)
45 (insert "(defvar foo)
46\(defvar foo bar \"baz\")
47\(require 'foo)")
48 (goto-char (point-min))
49 (should (checkdoc-next-docstring))
50 (should (looking-at-p "\"baz\")"))
51 (should-not (checkdoc-next-docstring))))
52
40;;; checkdoc-tests.el ends here 53;;; checkdoc-tests.el ends here