From b52393a87295df7d174d0c300510a2a2b134a6da Mon Sep 17 00:00:00 2001
From: Reese Williams <reese@reesew.io>
Date: Tue, 3 Jan 2023 09:24:18 +0000
Subject: [PATCH 1/2] Fixtures

---
 fixtures/small/endless_methods_actual.rb   | 13 +++++++++++++
 fixtures/small/endless_methods_expected.rb | 13 +++++++++++++
 2 files changed, 26 insertions(+)
 create mode 100644 fixtures/small/endless_methods_actual.rb
 create mode 100644 fixtures/small/endless_methods_expected.rb

diff --git a/fixtures/small/endless_methods_actual.rb b/fixtures/small/endless_methods_actual.rb
new file mode 100644
index 00000000..271248ac
--- /dev/null
+++ b/fixtures/small/endless_methods_actual.rb
@@ -0,0 +1,13 @@
+class ForWeiMu
+  def we_are_both(travelers) = "dark-eyed with love".uppercase
+  def self.and_both_possessed_of = white_cloud_mind
+
+  private def why_set_out_for = EastMountain.when_here!
+  def spring_grasses = grow_deeper_day.by_day?
+end
+
+def more_examples = begin
+  dangerous_stuff!
+rescue
+  puts "saved the day"
+end
diff --git a/fixtures/small/endless_methods_expected.rb b/fixtures/small/endless_methods_expected.rb
new file mode 100644
index 00000000..5a89bfc1
--- /dev/null
+++ b/fixtures/small/endless_methods_expected.rb
@@ -0,0 +1,13 @@
+class ForWeiMu
+  def we_are_both(travelers) = "dark-eyed with love".uppercase
+  def self.and_both_possessed_of = white_cloud_mind
+
+  private def why_set_out_for = EastMountain.when_here!
+  def spring_grasses = grow_deeper_day.by_day?
+end
+
+def more_examples = begin
+  dangerous_stuff!
+rescue
+  puts("saved the day")
+end

From 1c402ff262f71f6f6ab5bd83e7b9ab4952ad6c1b Mon Sep 17 00:00:00 2001
From: Reese Williams <reese@reesew.io>
Date: Tue, 3 Jan 2023 09:24:27 +0000
Subject: [PATCH 2/2] Add support for endless method definitions

---
 librubyfmt/src/format.rs            | 85 +++++++++++++++--------------
 librubyfmt/src/ripper_tree_types.rs | 14 ++++-
 2 files changed, 57 insertions(+), 42 deletions(-)

diff --git a/librubyfmt/src/format.rs b/librubyfmt/src/format.rs
index 9f3cc0b9..78f81482 100644
--- a/librubyfmt/src/format.rs
+++ b/librubyfmt/src/format.rs
@@ -18,35 +18,62 @@ pub fn format_def(ps: &mut dyn ConcreteParserState, def: Def) {
         ps.emit_indent();
     }
     ps.emit_def(def_expression.0);
+
+    format_def_body(ps, pp, *body, end_line);
+
+    if ps.at_start_of_line() {
+        ps.emit_newline();
+    }
+}
+
+fn format_def_body(
+    ps: &mut dyn ConcreteParserState,
+    pp: ParenOrParams,
+    bodystmt: DefBodyStmt,
+    end_line: LineNumber,
+) {
+    let has_end = matches!(bodystmt, DefBodyStmt::EndBodyStmt(..));
     ps.new_scope(Box::new(|ps| {
         format_paren_or_params(ps, pp);
 
         ps.with_formatting_context(
             FormattingContext::Def,
-            Box::new(|ps| {
-                ps.new_block(Box::new(|ps| {
-                    ps.emit_newline();
+            Box::new(|ps| match bodystmt {
+                DefBodyStmt::EndBodyStmt(bodystmt) => {
+                    ps.new_block(Box::new(|ps| {
+                        ps.emit_newline();
+                        ps.with_start_of_line(
+                            true,
+                            Box::new(|ps| {
+                                format_bodystmt(ps, Box::new(bodystmt), end_line);
+                            }),
+                        );
+                    }));
+                }
+                DefBodyStmt::EndlessBodyStmt(bodystmt) => {
+                    ps.emit_space();
+                    ps.emit_op("=".to_string());
+                    ps.emit_space();
+
                     ps.with_start_of_line(
-                        true,
+                        false,
                         Box::new(|ps| {
-                            format_bodystmt(ps, body, end_line);
+                            format_expression(ps, bodystmt.1);
                         }),
-                    );
-                }));
+                    )
+                }
             }),
         );
     }));
 
-    ps.with_start_of_line(
-        true,
-        Box::new(|ps| {
-            ps.wind_dumping_comments_until_line(end_line);
-            ps.emit_end();
-        }),
-    );
-
-    if ps.at_start_of_line() {
-        ps.emit_newline();
+    if has_end {
+        ps.with_start_of_line(
+            true,
+            Box::new(|ps| {
+                ps.wind_dumping_comments_until_line(end_line);
+                ps.emit_end();
+            }),
+        );
     }
 }
 
@@ -2252,32 +2279,10 @@ pub fn format_defs(ps: &mut dyn ConcreteParserState, defs: Defs) {
             ps.emit_dot();
             let (ident, linecol) = ident_or_kw.to_def_parts();
             handle_string_and_linecol(ps, ident, linecol);
-            format_paren_or_params(ps, paren_or_params);
         }),
     );
 
-    ps.with_formatting_context(
-        FormattingContext::Def,
-        Box::new(|ps| {
-            ps.new_block(Box::new(|ps| {
-                ps.emit_newline();
-                ps.with_start_of_line(
-                    true,
-                    Box::new(|ps| {
-                        format_bodystmt(ps, bodystmt, end_line);
-                    }),
-                );
-            }));
-        }),
-    );
-
-    ps.wind_dumping_comments_until_line(end_line);
-    ps.with_start_of_line(
-        true,
-        Box::new(|ps| {
-            ps.emit_end();
-        }),
-    );
+    format_def_body(ps, paren_or_params, *bodystmt, end_line);
 
     if ps.at_start_of_line() {
         ps.emit_newline();
diff --git a/librubyfmt/src/ripper_tree_types.rs b/librubyfmt/src/ripper_tree_types.rs
index d550d372..5cc53412 100644
--- a/librubyfmt/src/ripper_tree_types.rs
+++ b/librubyfmt/src/ripper_tree_types.rs
@@ -732,7 +732,7 @@ pub struct Def(
     pub def_tag,
     pub IdentOrOpOrKeywordOrConst,
     pub ParenOrParams,
-    pub Box<BodyStmt>,
+    pub Box<DefBodyStmt>,
     pub StartEnd,
 );
 
@@ -778,6 +778,16 @@ pub struct BodyStmt(
     pub Option<Ensure>,
 );
 
+// The bodystmt for endless defs
+#[derive(Deserialize, Debug, Clone)]
+pub struct EndlessBodyStmt(pub bodystmt_tag, pub Expression);
+
+#[derive(RipperDeserialize, Debug, Clone)]
+pub enum DefBodyStmt {
+    EndBodyStmt(BodyStmt),
+    EndlessBodyStmt(EndlessBodyStmt),
+}
+
 // deals with 2.6, where else is a vec expression and not an else
 #[derive(RipperDeserialize, Debug, Clone)]
 pub enum RescueElseOrExpressionList {
@@ -1693,7 +1703,7 @@ pub struct Defs(
     pub DotOrColon,
     pub IdentOrOpOrKeywordOrConst,
     pub ParenOrParams,
-    pub Box<BodyStmt>,
+    pub Box<DefBodyStmt>,
     pub StartEnd,
 );