Skip to content

Commit

Permalink
Calls with braces in interpolation for Style/MethodCallWithArgsParent…
Browse files Browse the repository at this point in the history
…heses

If we are calling methods in string interpolation with the `omit_parentheses`
style for the `Style/MethodCallWithArgsParentheses` cop, they are
currently forced to be without parentheses:

```ruby
"#{part 1}, #{part 2}, #{part 3}"
```

My coworkers at Dext want to be able to put spaces while calling methods
in interpolation, and I don't blame them. Having spaces reduces the
noise of following a method call in a string, especially if the string
happens to have multiple interpolations in it.

I want to add the `AllowParenthesesInStringInterpolation` cop configuration
that allows the use of parentheses in string interpolation calls.

```ruby
"#{part(1)}, #{part(2)}, #{part(3)}"
```
  • Loading branch information
gsamokovarov committed Mar 22, 2021
1 parent 1b910ce commit a34a957
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 0 deletions.
@@ -0,0 +1 @@
* [#9629](https://github.com/rubocop/rubocop/issues/9629): Add `AllowParenthesesInStringInterpolation` configuration to `Style/MethodCallWithArgsParentheses` to allow parenthesized calls in string interpolation. ([@gsamokovarov][])
1 change: 1 addition & 0 deletions config/default.yml
Expand Up @@ -3675,6 +3675,7 @@ Style/MethodCallWithArgsParentheses:
AllowParenthesesInMultilineCall: false
AllowParenthesesInChaining: false
AllowParenthesesInCamelCaseMethod: false
AllowParenthesesInStringInterpolation: false
EnforcedStyle: require_parentheses
SupportedStyles:
- require_parentheses
Expand Down
16 changes: 16 additions & 0 deletions lib/rubocop/cop/style/method_call_with_args_parentheses.rb
Expand Up @@ -146,6 +146,22 @@ module Style
#
# # good
# Array 1
#
# @example AllowParenthesesInStringInterpolation: false (default)
#
# # bad
# "#{t('this.is.bad')}"
#
# # good
# "#{t 'this.is.better'}"
#
# @example AllowParenthesesInStringInterpolation: true
#
# # good
# "#{t('this.is.good')}"
#
# # good
# "#{t 'this.is.also.good'}"
class MethodCallWithArgsParentheses < Base
require_relative 'method_call_with_args_parentheses/omit_parentheses'
require_relative 'method_call_with_args_parentheses/require_parentheses'
Expand Down
Expand Up @@ -5,25 +5,29 @@ module Cop
module Style
class MethodCallWithArgsParentheses
# Style omit_parentheses
# rubocop:disable Metrics/ModuleLength
module OmitParentheses
TRAILING_WHITESPACE_REGEX = /\s+\Z/.freeze
OMIT_MSG = 'Omit parentheses for method calls with arguments.'
private_constant :OMIT_MSG

private

# rubocop:disable Metrics/CyclomaticComplexity
def omit_parentheses(node)
return unless node.parenthesized?
return if inside_endless_method_def?(node)
return if node.implicit_call?
return if super_call_without_arguments?(node)
return if allowed_camel_case_method_call?(node)
return if legitimate_call_with_parentheses?(node)
return if allowed_string_interpolation_method_call?(node)

add_offense(offense_range(node), message: OMIT_MSG) do |corrector|
auto_correct(corrector, node)
end
end
# rubocop:enable Metrics/CyclomaticComplexity

def auto_correct(corrector, node)
if parentheses_at_the_end_of_multiline_call?(node)
Expand Down Expand Up @@ -53,6 +57,11 @@ def allowed_camel_case_method_call?(node)
cop_config['AllowParenthesesInCamelCaseMethod'])
end

def allowed_string_interpolation_method_call?(node)
cop_config['AllowParenthesesInStringInterpolation'] &&
inside_string_interpolation?(node)
end

def parentheses_at_the_end_of_multiline_call?(node)
node.multiline? &&
node.loc.begin.source_line
Expand Down Expand Up @@ -172,7 +181,12 @@ def assigned_before?(node, target)
node.assignment? &&
node.loc.operator.begin < target.loc.begin
end

def inside_string_interpolation?(node)
node.ancestors.drop_while { |a| !a.begin_type? }.any?(&:dstr_type?)
end
end
# rubocop:enable Metrics/ModuleLength
end
end
end
Expand Down
27 changes: 27 additions & 0 deletions spec/rubocop/cop/style/method_call_with_args_parentheses_spec.rb
Expand Up @@ -467,6 +467,17 @@ def foo
RUBY
end

it 'register an offense for parens in string interpolation' do
expect_offense(<<~'RUBY')
"#{t('no.parens')}"
^^^^^^^^^^^^^ Omit parentheses for method calls with arguments.
RUBY

expect_correction(<<~'RUBY')
"#{t 'no.parens'}"
RUBY
end

it 'register an offense in complex conditionals' do
expect_offense(<<~RUBY)
def foo
Expand Down Expand Up @@ -831,6 +842,22 @@ def seatle_style arg: default(42)
end
end

context 'allowing parens in string interpolation' do
let(:cop_config) do
{
'EnforcedStyle' => 'omit_parentheses',
'AllowParenthesesInStringInterpolation' => true
}
end

it 'accepts parens for camel-case method names' do
expect_no_offenses(<<~'RUBY')
"#{t('this.is.good')}"
"#{t 'this.is.also.good'}"
RUBY
end
end

context 'when inspecting macro methods with IncludedMacros' do
let(:cop_config) do
{
Expand Down

0 comments on commit a34a957

Please sign in to comment.