From a5651c0c403bb6513e235056d787611059f6d568 Mon Sep 17 00:00:00 2001
From: Dmitry Gutov <dgutov@yandex.ru>
Date: Thu, 9 Feb 2023 04:15:41 +0200
Subject: [PATCH] ruby-ts-mode: Fix indentation inside empty if/unless/case/def

* lisp/progmodes/ruby-ts-mode.el (ruby-ts--indent-rules):
Add new rule.

* test/lisp/progmodes/ruby-ts-mode-tests.el
(ruby-ts-indent-empty-if-else): New test.
---
 lisp/progmodes/ruby-ts-mode.el            |  7 +++++++
 test/lisp/progmodes/ruby-ts-mode-tests.el | 16 ++++++++++++++++
 2 files changed, 23 insertions(+)

diff --git a/lisp/progmodes/ruby-ts-mode.el b/lisp/progmodes/ruby-ts-mode.el
index e83bc2f9e11..20ffb38fb88 100644
--- a/lisp/progmodes/ruby-ts-mode.el
+++ b/lisp/progmodes/ruby-ts-mode.el
@@ -661,6 +661,13 @@ a statement container is a node that matches
            ((n-p-gp nil "body_statement" ,ruby-ts--method-regex) ;other statements
             (ruby-ts--align-keywords ruby-ts--grand-parent-node) ruby-indent-level)
 
+           ;; Quirk of the ruby parser: these "alignable" nodes don't
+           ;; have the "container" child node when there are no
+           ;; statements inside. Thus we have to have a separate rule
+           ;; for the "empty if/unless/case/def" situation.
+           ((match "\\`\\'" "\\`\\(?:if\\|unless\\|case\\|method\\)\\'")
+            (ruby-ts--align-keywords ruby-ts--parent-node) ruby-indent-level)
+
            ;; Chained calls:
            ;; if `ruby-align-chained-calls' is true, the first query
            ;; matches and the node is aligned under the first dot (.);
diff --git a/test/lisp/progmodes/ruby-ts-mode-tests.el b/test/lisp/progmodes/ruby-ts-mode-tests.el
index 18e3e60a04a..c99e1a43063 100644
--- a/test/lisp/progmodes/ruby-ts-mode-tests.el
+++ b/test/lisp/progmodes/ruby-ts-mode-tests.el
@@ -122,6 +122,22 @@ The whitespace before and including \"|\" on each line is removed."
     (funcall indent-line-function)
     (should (= (current-indentation) ruby-indent-level))))
 
+(ert-deftest ruby-ts-indent-empty-if-else ()
+  (skip-unless (treesit-ready-p 'ruby t))
+  (let* ((str "c = if foo
+      zz
+    else
+      zz
+    end
+"))
+    (ruby-ts-with-temp-buffer str
+      (goto-char (point-min))
+      (dotimes (_ 2)
+        (re-search-forward "^ *zz")
+        (replace-match "")
+        (funcall indent-line-function)
+        (should (= (current-indentation) 6))))))
+
 (ert-deftest ruby-ts-add-log-current-method-examples ()
   (skip-unless (treesit-ready-p 'ruby t))
   (let ((pairs '(("foo" . "#foo")
-- 
2.39.5