ruby-syntax-tree / syntax_tree

Interact with the Ruby syntax tree

Home Page:https://ruby-syntax-tree.github.io/syntax_tree/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Multiline blocks sometimes use braces, sometimes do/end

etiennebarrie opened this issue · comments

This shows the issue with fixtures:

diff --git i/test/fixtures/lambda.rb w/test/fixtures/lambda.rb
index 5dba3be..079c082 100644
--- i/test/fixtures/lambda.rb
+++ w/test/fixtures/lambda.rb
@@ -80,3 +80,83 @@
 -> do # comment1
   # comment2
 end
+% # multiline lambda
+-> {
+  multi
+  line
+}
+-
+-> do
+  multi
+  line
+end
+% # multiline lambda inside a method
+def foo
+  -> {
+    multi
+    line
+  }
+end
+-
+def foo
+  -> do
+    multi
+    line
+  end
+end
+% # nested multiline lambda
+-> {
+  -> {
+    multi
+    line
+  }
+}
+-
+-> do
+  -> do
+    multi
+    line
+  end
+end
+% # multiline lambda in a method_add_block
+method_add_block {
+  -> {
+    multi
+    line
+  }
+}
+-
+method_add_block do
+  -> do
+    multi
+    line
+  end
+end
+% # multiline lambda in a method_add_block with arguments
+method_add_block("arg") {
+  -> {
+    multi
+    line
+  }
+}
+-
+method_add_block("arg") do
+  -> do
+    multi
+    line
+  end
+end
+% # multiline lamda in a command
+command "arg" do
+  -> {
+    multi
+    line
+  }
+end
+-
+command "arg" do
+  -> do
+    multi
+    line
+  end
+end
  • The first case shows that multiline lambdas get formatted with do/end
  • The second case shows that multiline lambdas get formatted with do/end inside methods
  • The third case shows that multiline lambdas get formatted with do/end when nested
  • The fourth case shows that multiline lambdas get formatted with do/end when passed as a block in a method call without arguments (parsed as a method_add_block)
  • The fifth case shows that multiline lambdas get formatted with do/end when passed as a block in a method call with arguments but with parentheses (parsed as a method_add_block)
  • The sixth case is failing, shows that multiline lambdas get formatted with braces when passed as a block in a method call with arguments but no parentheses (which is parsed as a command)

Additionally, Rubocop is fine with braces for multiline lambdas because method calls to lambda (including stabby lambdas), proc and it are special-cased: https://github.com/rubocop/rubocop/blob/1884a46d9284b47a07763e2506276662c7c1ae6e/config/default.yml#L3212-L3214

If we remove that special handling, Rubocop will always enforce using do/end for multiline blocks, but stree write will force braces, when called in a method call with arguments but no parentheses, typically in tests in Rails with ActiveSupport::Testing::Declarative:

class SomeTest < ActiveSupport::TestCase
  test "something" do
    _ = -> do
      multi
      line
    end
  end
end

That makes rubocop and stree incompatible for that rule. Once the formatting is fixed to always generate do/end for multiline lambdas, we could add this to config/rubocop.yml to make them compatible:

Style/BlockDelimiters:
  AllowedMethods: []