Subject: bug#26619: 26.0.50; Wrong indentation in emacs-lisp-mode

From: [email-masked]
Date: Tue, 25 Apr 2017 23:22:10 -0400

Kaushal Modi <[email-masked]> writes:

>
> But indentation is still broken in cases like these:
>
> (with-eval-after-load 'foo
> (setq bar `(
> baz)))
>

Michael Heerdegen <[email-masked]> writes:
>
> There must be more cases.  I already get wrong indentation with very
> simple cases.  E.g. here:
>
> #+begin_src emacs-lisp
> (defun test ()
>   "A test function"
>   (switch-to-buffer "*Messages*")
>   17)
> #+end_src

Hmm, I was too aggressive about preserving the last sexp position of the
parse state.  The following patch fixes both these cases for
indent-region (it applies on top of the previous one), though it needs
to be redone more cleanly.

>From 101fa466c3e5303458dc6abd2d24ef55d508d9cd Mon Sep 17 00:00:00 2001
From: Noam Postavsky <[email-masked]>
Date: Tue, 25 Apr 2017 23:16:12 -0400
Subject: [PATCH v1 2/2] [WIP] Fix additional indentation problems (Bug#26619)

* lisp/emacs-lisp/lisp-mode.el (lisp-indent-region): Don't use last
sexp from different depths.
---
 lisp/emacs-lisp/lisp-mode.el | 34 ++++++++++++++++++++++++----------
 1 file changed, 24 insertions(+), 10 deletions(-)

diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el
index d619dd8f4c..12fd53140c 100644
--- a/lisp/emacs-lisp/lisp-mode.el
+++ b/lisp/emacs-lisp/lisp-mode.el
@@ -811,14 +811,25 @@ lisp-indent-region
         (unless (and (bolp) (eolp))
           (lisp-indent-line (funcall calc-indent parse-state)))
         (forward-line 1)
-        (let ((last-sexp (nth 2 parse-state)))
-          (setq parse-state (parse-partial-sexp last-syntax-point (point)
-                                                nil nil parse-state))
-          ;; It's important to preserve last sexp location for
-          ;; `calculate-lisp-indent'.
-          (unless (nth 2 parse-state)
-            (setf (nth 2 parse-state) last-sexp))
-          (setq last-syntax-point (point)))
+        (let ((oldstate parse-state)
+              (target-point (point)))
+          (while
+              (progn
+                (setq parse-state (parse-partial-sexp last-syntax-point target-point
+                                                      nil t oldstate))
+                (if (>= (point) target-point)
+                    nil                   ; Done.
+                  (when (= (nth 0 parse-state) (nth 0 oldstate)) ; Stopped before open paren.
+                    (setq parse-state (parse-partial-sexp last-syntax-point target-point
+                                                          (1+ (nth 0 parse-state)) nil parse-state)))
+                  (setq last-syntax-point (point))
+                  ;; It's important to preserve last sexp location for
+                  ;; `calculate-lisp-indent', but it's only relevant at the
+                  ;; same depth.
+                  (unless (or (nth 2 parse-state) (/= (nth 0 parse-state) (nth 0 oldstate)))
+                    (setf (nth 2 parse-state) (nth 2 oldstate)))
+                  t))
+            (setq oldstate parse-state)))
         ;; Update cache's depth stack.
         (funcall calc-indent (car parse-state))
         (and pr (progress-reporter-update pr (point))))
@@ -1169,7 +1180,8 @@ indent-sexp
         ;; Parse this line so we can learn the state to indent the
         ;; next line.  Preserve element 2 of the state (last sexp) for
         ;; `calculate-lisp-indent'.
-        (let ((last-sexp (nth 2 state)))
+        (let ((last-depth (nth 0 state))
+              (last-sexp (nth 2 state)))
           (while (progn
                    (setq state (parse-partial-sexp
                                 last-syntax-point (progn (end-of-line) (point))
@@ -1179,7 +1191,9 @@ indent-sexp
                    (nth 3 state))
             (setq state (parse-partial-sexp (point) (point-max)
                                             nil nil state 'syntax-table))
-            (setq last-sexp (or (nth 2 state) last-sexp))
+            (when (nth 2 state)
+              (setq last-sexp (nth 2 state))
+              (setq last-depth (nth 0 state)))
             (setq last-syntax-point (point)))
           (setf (nth 2 state) last-sexp))
         ;; Update cache's depth stack.
-- 
2.11.1