From ef16339918e3f31831dd271cde40cb2072069875 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Daniel=20Mart=C3=ADn?= Date: Sun, 25 Jun 2023 22:17:14 +0200 Subject: [PATCH] Make js-beginning-of-defun return non-nil on success The docstring of 'beginning-of-defun-function' says that the function shall return non-nil when it found the beginning of a defun. This is specially important because the calling code decides when to move point depending on the return value. * lisp/progmodes/js.el (js-beginning-of-defun) (js--beginning-of-defun-flat): Return non-nil when the beginning of a defun is found. (Bug#64283) * test/lisp/progmodes/js-tests.el (js-mode-end-of-defun): Add a unit test. --- lisp/progmodes/js.el | 61 ++++++++++++++++++--------------- test/lisp/progmodes/js-tests.el | 51 +++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 27 deletions(-) diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el index 414b6eb2baf..a05bd758dbc 100644 --- a/lisp/progmodes/js.el +++ b/lisp/progmodes/js.el @@ -1024,38 +1024,45 @@ Return the pitem of the function we went to the beginning of." "Helper function for `js-beginning-of-defun'." (let ((pstate (js--beginning-of-defun-raw))) (when pstate - (goto-char (js--pitem-h-begin (car pstate)))))) + (goto-char (js--pitem-h-begin (car pstate))) + t))) (defun js-beginning-of-defun (&optional arg) "Value of `beginning-of-defun-function' for `js-mode'." (setq arg (or arg 1)) - (while (and (not (eobp)) (< arg 0)) - (cl-incf arg) - (when (and (not js-flat-functions) - (or (eq (js-syntactic-context) 'function) - (js--function-prologue-beginning))) - (js-end-of-defun)) - - (if (js--re-search-forward - "\\_" nil t) - (goto-char (js--function-prologue-beginning)) - (goto-char (point-max)))) - - (while (> arg 0) - (cl-decf arg) - ;; If we're just past the end of a function, the user probably wants - ;; to go to the beginning of *that* function - (when (eq (char-before) ?}) - (backward-char)) - - (let ((prologue-begin (js--function-prologue-beginning))) - (cond ((and prologue-begin (< prologue-begin (point))) - (goto-char prologue-begin)) + (let ((found)) + (while (and (not (eobp)) (< arg 0)) + (cl-incf arg) + (when (and (not js-flat-functions) + (or (eq (js-syntactic-context) 'function) + (js--function-prologue-beginning))) + (js-end-of-defun)) + + (if (js--re-search-forward + "\\_" nil t) + (progn (goto-char (js--function-prologue-beginning)) + (setq found t)) + (goto-char (point-max)) + (setq found nil))) + + (while (> arg 0) + (cl-decf arg) + ;; If we're just past the end of a function, the user probably wants + ;; to go to the beginning of *that* function + (when (eq (char-before) ?}) + (backward-char)) - (js-flat-functions - (js--beginning-of-defun-flat)) - (t - (js--beginning-of-defun-nested)))))) + (let ((prologue-begin (js--function-prologue-beginning))) + (cond ((and prologue-begin (< prologue-begin (point))) + (goto-char prologue-begin) + (setq found t)) + + (js-flat-functions + (setq found (js--beginning-of-defun-flat))) + (t + (when (js--beginning-of-defun-nested) + (setq found t)))))) + found)) (defun js--flush-caches (&optional beg _ignored) "Flush the `js-mode' syntax cache after position BEG. diff --git a/test/lisp/progmodes/js-tests.el b/test/lisp/progmodes/js-tests.el index 00fa78e8891..5db92b08f8a 100644 --- a/test/lisp/progmodes/js-tests.el +++ b/test/lisp/progmodes/js-tests.el @@ -237,6 +237,57 @@ if (!/[ (:,='\"]/.test(value)) { (js-deftest-indent "jsx-unclosed-2.jsx") (js-deftest-indent "jsx.jsx") +;;;; Navigation tests. + +(ert-deftest js-mode-beginning-of-defun () + (with-temp-buffer + (insert "function foo() { + var value = 1; +} + +/** A comment. */ +function bar() { + var value = 1; +} +") + (js-mode) + ;; Move point inside `foo'. + (goto-char 18) + (beginning-of-defun) + (should (bobp)) + ;; Move point between the two functions. + (goto-char 37) + (beginning-of-defun) + (should (bobp)) + ;; Move point inside `bar'. + (goto-char 73) + (beginning-of-defun) + ;; Point should move to the beginning of `bar'. + (should (equal (point) 56)))) + +(ert-deftest js-mode-end-of-defun () + (with-temp-buffer + (insert "function foo() { + var value = 1; +} + +/** A comment. */ +function bar() { + var value = 1; +} +") + (js-mode) + (goto-char (point-min)) + (end-of-defun) + ;; end-of-defun from the beginning of the buffer should go to the + ;; end of `foo'. + (should (equal (point) 37)) + ;; Move point to the beginning of /** A comment. */ + (goto-char 38) + (end-of-defun) + ;; end-of-defun should move point to eob. + (should (eobp)))) + (provide 'js-tests) ;;; js-tests.el ends here -- 2.39.2