From: Jackson Ray Hamilton Date: Tue, 26 Mar 2019 03:39:48 +0000 (-0700) Subject: Fix counting of nested self-closing JSXOpeningElements X-Git-Tag: emacs-27.0.90~3261^2~45 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=16669d7c5d5a0dfadf672f8359e431ef81044a23;p=emacs.git Fix counting of nested self-closing JSXOpeningElements * lisp/progmodes/js.el (js-jsx--matching-close-tag-pos): Fix bug where self-closing JSXOpeningElements might be missed if one was nested within another. * test/manual/indent/jsx-self-closing.jsx: Add test for bug concerning self-closing JSXOpeningElement counting. --- diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el index f8dd72c22bc..f22c68cff95 100644 --- a/lisp/progmodes/js.el +++ b/lisp/progmodes/js.el @@ -1934,40 +1934,29 @@ Assuming a JSXOpeningElement or a JSXOpeningFragment is immediately before point, find a matching JSXClosingElement or JSXClosingFragment, skipping over any nested JSXElements to find the match. Return nil if a match can’t be found." - (let ((tag-stack 1) self-closing-pos type) + (let ((tag-stack 1) type tag-pos last-pos pos) (catch 'stop (while (re-search-forward js-jsx--tag-re nil t) - (setq type (js-jsx--matched-tag-type)) - ;; Balance the total of self-closing tags that we subtract - ;; from the stack, ignoring those tags which are never added - ;; to the stack (see below). - (unless (eq type 'self-closing) - (when (and self-closing-pos (> (point) self-closing-pos)) + (setq type (js-jsx--matched-tag-type) + tag-pos (match-beginning 0)) + ;; Clear the stack of any JSXOpeningElements which turned out + ;; to be self-closing. + (when last-pos + (setq pos (point)) + (goto-char last-pos) + (while (re-search-forward js-jsx--self-closing-re pos 'move) (setq tag-stack (1- tag-stack)))) (if (eq type 'close) (progn (setq tag-stack (1- tag-stack)) (when (= tag-stack 0) - (throw 'stop (match-beginning 0)))) - ;; Tags that we know are self-closing aren’t added to the - ;; stack at all, because we only close the ones that we have - ;; anticipated after moving past those anticipated tags’ - ;; ends, and if a self-closing tag is the first tag we - ;; encounter in this loop, then it will never be anticipated - ;; (due to an optimization where we sometimes can avoid - ;; looking for self-closing tags). + (throw 'stop tag-pos))) + ;; JSXOpeningElements that we know are self-closing aren’t + ;; added to the stack at all (since re-search-forward moves + ;; point after their self-closing syntax). (unless (eq type 'self-closing) (setq tag-stack (1+ tag-stack)))) - ;; Don’t needlessly recalculate. - (unless (and self-closing-pos (<= (point) self-closing-pos)) - (setq self-closing-pos nil) ; Reset if recalculating. - (save-excursion - ;; Anticipate a self-closing tag that we should make sure - ;; to subtract from the tag stack once we move past its - ;; end; we might might miss the end otherwise, due to the - ;; regexp-matching method we use to detect tags. - (when (re-search-forward js-jsx--self-closing-re nil t) - (setq self-closing-pos (match-beginning 0))))))))) + (setq last-pos (point)))))) (defun js-jsx--enclosing-curly-pos () "Return position of enclosing “{” in a “{/}” pair about point." diff --git a/test/manual/indent/jsx-self-closing.jsx b/test/manual/indent/jsx-self-closing.jsx new file mode 100644 index 00000000000..f8ea7a138ad --- /dev/null +++ b/test/manual/indent/jsx-self-closing.jsx @@ -0,0 +1,13 @@ +// Local Variables: +// indent-tabs-mode: nil +// js-indent-level: 2 +// End: + +// The following test goes below any comments to avoid including +// misindented comments among the erroring lines. + +// Properly parse/indent code with a self-closing tag inside the +// attribute of another self-closing tag. +
+
} /> +