diff --git a/fixtures/small/prism/expression_calls_actual.rb b/fixtures/small/prism/expression_calls_actual.rb new file mode 100644 index 00000000..71d8250e --- /dev/null +++ b/fixtures/small/prism/expression_calls_actual.rb @@ -0,0 +1,47 @@ +[ + CommonFields::OBVIOUSLY, + CommonFields::THESE, + CommonFields::ARE, + CommonFields::FAKE_RESOURCE.with_wombo(true).with_combo(true).with_explosion(true) +].map do |field| + # Swap things out, to make sure. + override || field +end + +{ + having: "Having a Coke With You", + with: you +}.freeze + +{ + having: "Having a Coke With You", + with: you +} # by Mark Leidner + .freeze + +{ + having: "Having a Coke With You", + with: you +}.# by Mark Leidner +freeze + +{ + having: "Having a Coke With You", + with: you +} +# by Mark Leidner +.freeze + +{ + something: "wicked" +}.this_way { + comes + # spookyyyy +} + +{musical: "wicked"} + # The original broadway cast recording! + .sing("Defying Gravity") + +{musical: "wicked"} + .sing("Defying Gravity") # The original broadway cast recording! diff --git a/fixtures/small/prism/expression_calls_expected.rb b/fixtures/small/prism/expression_calls_expected.rb new file mode 100644 index 00000000..0db74275 --- /dev/null +++ b/fixtures/small/prism/expression_calls_expected.rb @@ -0,0 +1,48 @@ +[ + CommonFields::OBVIOUSLY, + CommonFields::THESE, + CommonFields::ARE, + CommonFields::FAKE_RESOURCE.with_wombo(true).with_combo(true).with_explosion(true) +].map do |field| + # Swap things out, to make sure. + override || field +end + +{ + having: "Having a Coke With You", + with: you +}.freeze + +{ + having: "Having a Coke With You", + with: you + # by Mark Leidner +}.freeze + +{ + having: "Having a Coke With You", + with: you + # by Mark Leidner +}.freeze + +{ + having: "Having a Coke With You", + with: you +} + # by Mark Leidner + .freeze + +{ + something: "wicked" +}.this_way { + comes + # spookyyyy +} + +{musical: "wicked"} + # The original broadway cast recording! + .sing("Defying Gravity") + +{musical: "wicked"} + # The original broadway cast recording! + .sing("Defying Gravity") diff --git a/librubyfmt/src/format_prism.rs b/librubyfmt/src/format_prism.rs index f79483e5..50b11856 100644 --- a/librubyfmt/src/format_prism.rs +++ b/librubyfmt/src/format_prism.rs @@ -2351,23 +2351,34 @@ fn call_chain_elements_are_user_multilined<'src>( | prism::Node::ParenthesesNode { .. } ); - // _However_, don't ignore this if there are comments in the call chain though; this check may - // cause it to single-lined, which breaks comment rendering. Specifically, we're checking - // for comments in between the receiver expression and the following message, e.g. - // ```ruby - // [stuff] - // # spooky comment - // .freeze - // ``` - // For cases without the comment, we'd usually put this all on one line, but if we force - // it all on one line, this will break the comment insertion logic, and given the comment's - // placement, the user probably intended to break this onto multiple lines anyways. - let has_comment = ps.has_comment_in_offset_span( - call_chain_elements[0].location().end_offset(), - start_loc_for_call_node_in_chain(&call_chain_elements[1].as_call_node().unwrap()), - ); - if is_literal_expression && !has_comment { - call_chain_elements = &call_chain_elements[1..]; + if is_literal_expression { + // _However_, don't ignore this if there are comments in the call chain though; this check may + // cause it to single-lined, which breaks comment rendering. Specifically, we're checking + // for comments in between the receiver expression and the following message, e.g. + // ```ruby + // [stuff] + // # spooky comment + // .freeze + // ``` + // For cases without the comment, we'd usually put this all on one line, but if we force + // it all on one line, this will break the comment insertion logic, and given the comment's + // placement, the user probably intended to break this onto multiple lines anyways. + let first_call_start_line = ps.get_line_number_for_offset( + start_loc_for_call_node_in_chain(&call_chain_elements[1].as_call_node().unwrap()), + ); + let leading_expr_end_line = + ps.get_line_number_for_offset(call_chain_elements[0].location().end_offset()); + + // Note: We check from `leading_expr_end_line + 1` because comments on the same line as + // the closing brace will be rendered into the breakable during formatting, so they don't + // affect whether we should multiline the call chain. We check `first_call_start_line + 1` + // because the range checked by `has_comments_in_line` is non-inclusive. + let has_comment_between_expression_and_call = + ps.has_comments_in_line(leading_expr_end_line + 1, first_call_start_line + 1); + + if !has_comment_between_expression_and_call { + call_chain_elements = &call_chain_elements[1..]; + } } }