aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJackson Ray Hamilton2019-03-25 20:39:48 -0700
committerJackson Ray Hamilton2019-04-08 22:48:23 -0700
commit16669d7c5d5a0dfadf672f8359e431ef81044a23 (patch)
tree55d370ebbabd90345a34f081772a5a1ef81e7021
parent84b1cfbc2d6b9236913a18ed192798fd530911db (diff)
downloademacs-16669d7c5d5a0dfadf672f8359e431ef81044a23.tar.gz
emacs-16669d7c5d5a0dfadf672f8359e431ef81044a23.zip
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.
-rw-r--r--lisp/progmodes/js.el39
-rw-r--r--test/manual/indent/jsx-self-closing.jsx13
2 files changed, 27 insertions, 25 deletions
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
1934immediately before point, find a matching JSXClosingElement or 1934immediately before point, find a matching JSXClosingElement or
1935JSXClosingFragment, skipping over any nested JSXElements to find 1935JSXClosingFragment, skipping over any nested JSXElements to find
1936the match. Return nil if a match can’t be found." 1936the match. Return nil if a match can’t be found."
1937 (let ((tag-stack 1) self-closing-pos type) 1937 (let ((tag-stack 1) type tag-pos last-pos pos)
1938 (catch 'stop 1938 (catch 'stop
1939 (while (re-search-forward js-jsx--tag-re nil t) 1939 (while (re-search-forward js-jsx--tag-re nil t)
1940 (setq type (js-jsx--matched-tag-type)) 1940 (setq type (js-jsx--matched-tag-type)
1941 ;; Balance the total of self-closing tags that we subtract 1941 tag-pos (match-beginning 0))
1942 ;; from the stack, ignoring those tags which are never added 1942 ;; Clear the stack of any JSXOpeningElements which turned out
1943 ;; to the stack (see below). 1943 ;; to be self-closing.
1944 (unless (eq type 'self-closing) 1944 (when last-pos
1945 (when (and self-closing-pos (> (point) self-closing-pos)) 1945 (setq pos (point))
1946 (goto-char last-pos)
1947 (while (re-search-forward js-jsx--self-closing-re pos 'move)
1946 (setq tag-stack (1- tag-stack)))) 1948 (setq tag-stack (1- tag-stack))))
1947 (if (eq type 'close) 1949 (if (eq type 'close)
1948 (progn 1950 (progn
1949 (setq tag-stack (1- tag-stack)) 1951 (setq tag-stack (1- tag-stack))
1950 (when (= tag-stack 0) 1952 (when (= tag-stack 0)
1951 (throw 'stop (match-beginning 0)))) 1953 (throw 'stop tag-pos)))
1952 ;; Tags that we know are self-closing aren’t added to the 1954 ;; JSXOpeningElements that we know are self-closing aren’t
1953 ;; stack at all, because we only close the ones that we have 1955 ;; added to the stack at all (since re-search-forward moves
1954 ;; anticipated after moving past those anticipated tags’ 1956 ;; point after their self-closing syntax).
1955 ;; ends, and if a self-closing tag is the first tag we
1956 ;; encounter in this loop, then it will never be anticipated
1957 ;; (due to an optimization where we sometimes can avoid
1958 ;; looking for self-closing tags).
1959 (unless (eq type 'self-closing) 1957 (unless (eq type 'self-closing)
1960 (setq tag-stack (1+ tag-stack)))) 1958 (setq tag-stack (1+ tag-stack))))
1961 ;; Don’t needlessly recalculate. 1959 (setq last-pos (point))))))
1962 (unless (and self-closing-pos (<= (point) self-closing-pos))
1963 (setq self-closing-pos nil) ; Reset if recalculating.
1964 (save-excursion
1965 ;; Anticipate a self-closing tag that we should make sure
1966 ;; to subtract from the tag stack once we move past its
1967 ;; end; we might might miss the end otherwise, due to the
1968 ;; regexp-matching method we use to detect tags.
1969 (when (re-search-forward js-jsx--self-closing-re nil t)
1970 (setq self-closing-pos (match-beginning 0)))))))))
1971 1960
1972(defun js-jsx--enclosing-curly-pos () 1961(defun js-jsx--enclosing-curly-pos ()
1973 "Return position of enclosing “{” in a “{/}” pair about point." 1962 "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 @@
1// Local Variables:
2// indent-tabs-mode: nil
3// js-indent-level: 2
4// End:
5
6// The following test goes below any comments to avoid including
7// misindented comments among the erroring lines.
8
9// Properly parse/indent code with a self-closing tag inside the
10// attribute of another self-closing tag.
11<div>
12 <div attr={() => <div attr="" />} />
13</div>