branch: elpa/go-mode
commit e10d6775f486ef09ed993567b0bd2c69f35deb45
Author: Muir Manders <[email protected]>
Commit: Peter Sanford <[email protected]>

    indent: fix func literals in dangling lines
    
    Fix cases like:
    
    foo &&
      bar(func() {
      X // Bad
      })
    
    foo &&
      bar(func() {
        X // Good
      })
    
    When computing indent for "X" we were misinterpreting the enclosing
    "{" as a control flow block opener as in:
    
    foo &&
      bar {
      X
    }
    
    Now we better differentiate func literal opening curlies and control
    flow block curlies.
    
    Fixes #332.
    
    Closes: #333 [via git-merge-pr]
---
 go-mode.el                                       | 51 ++++++++++++++++++++----
 test/testdata/indentation_tests/function_call.go | 16 ++++++++
 2 files changed, 59 insertions(+), 8 deletions(-)

diff --git a/go-mode.el b/go-mode.el
index 600b6c4..a0b72be 100644
--- a/go-mode.el
+++ b/go-mode.el
@@ -865,7 +865,7 @@ is done."
           (first t)
 
           ;; Whether we start in a block (i.e. our first line is not a
-          ;; continuation line and is in an "if", "for", "func" etc. block).
+          ;; continuation line and is in an "if", "for", etc. block).
           (in-block)
 
           ;; Our desired indent relative to our ending line's indent.
@@ -942,10 +942,7 @@ is done."
             ;; If we aren't a continuation line and we have an enclosing paren
             ;; or brace, jump to opener and increment our indent.
             (when (go-goto-opening-parenthesis)
-              ;; We started in a child block if our opener is a curly brace.
-              (setq in-block (and
-                              (eq (char-after) ?{)
-                              (looking-back "[^[:space:]][[:space:]]" (- 
(point) 2))))
+              (setq in-block (go--flow-block-p))
               (cl-incf indent tab-width))))
 
         ;; If we started in a child block we must follow dangling lines
@@ -959,7 +956,8 @@ is done."
         ;; There can be an arbitrary number of indents, so we must go back to
         ;; the "if" to determine the indent of "X".
         (when (and in-block (bolp) (go-previous-line-has-dangling-op-p))
-          (goto-char (go-previous-line-has-dangling-op-p))))
+          (goto-char (go-previous-line-has-dangling-op-p)))
+        )
 
       ;; If our ending line is a continuation line but doesn't open
       ;; an extra indent, reduce indent. We tentatively gave indents to all
@@ -1007,6 +1005,32 @@ are loose binding expression separators."
     (|| 1)
     (t 0)))
 
+(defun go--flow-block-p ()
+  "Return whether looking at a { that opens a control flow block.
+
+We check for a { that is preceded by a space and is not a func
+literal opening brace."
+  (save-excursion
+    (when (and
+           (eq (char-after) ?{)
+           (not (zerop (skip-syntax-backward " "))))
+
+      (let ((eol (line-end-position))
+            (level (go-paren-level))
+            (found-func-literal))
+
+        (beginning-of-line)
+
+        ;; See if we find any "func" keywords on this line at the same paren
+        ;; level as the curly.
+        (while (and
+                (not found-func-literal)
+                (re-search-forward "\\_<func\\_>" eol t))
+          (setq found-func-literal (and
+                                    (= level (go-paren-level))
+                                    (not (go-in-string-or-comment-p)))))
+        (not found-func-literal)))))
+
 (defun go--continuation-line-indents-p ()
   "Return non-nil if the current continuation line opens an additional indent.
 
@@ -1037,8 +1061,19 @@ foo ||
       (when (or
              ;; We can only open indent if we have a dangling operator, or
              (go--current-line-has-dangling-op-p)
-             ;; we end in an opening paren/brace or comma.
-             (go--line-suffix-p "[(,]\\|[^[:space:]]{"))
+
+             (save-excursion
+               (go--end-of-line)
+               (backward-char)
+               (or
+                ;; Line ends in a "(" or ",", or
+                (eq (char-after) ?\()
+                (eq (char-after) ?,)
+
+                ;; Line ends in a "{" that isn't a control block.
+                (and
+                 (eq (char-after) ?{)
+                 (not (go--flow-block-p))))))
 
         (let ((prev-precedence (go--operator-precedence prev-op))
               (start-depth (go-paren-level))
diff --git a/test/testdata/indentation_tests/function_call.go 
b/test/testdata/indentation_tests/function_call.go
index 3222bd7..c579a19 100644
--- a/test/testdata/indentation_tests/function_call.go
+++ b/test/testdata/indentation_tests/function_call.go
@@ -61,4 +61,20 @@ func _() {
                1,
        ),
        )
+
+       foo.
+               bar(func(i int) (a b) {
+
+               })
+
+       foo ||
+               bar &&
+                       baz(func() {
+                               X
+                       })
+
+       foo &&
+               func() bool {
+                       return X
+               }()
 }

Reply via email to