From eaab0f878bf5e48c616c5ac5d5ce12528e47524c Mon Sep 17 00:00:00 2001 From: Daniel Azuma Date: Tue, 8 Jan 2019 15:01:35 -0800 Subject: [PATCH] Add AllowParenthesesInCamelCaseMethod option This option on the Style/MethodCallWithArgsParentheses cop takes effect when EnforcedStyle:omit_parentheses. If true, CamelCase methods (with names beginning with a capital letter) may be called with parentheses even when taking arguments. Even though this case isn't syntactically ambiguous, it is sometimes preferred in order to make it more obvious that a method is being called rather than a constant referenced. --- CHANGELOG.md | 5 +++ .../method_call_with_args_parentheses.rb | 32 ++++++++++++++++--- manual/cops_style.md | 24 +++++++++++++- .../method_call_with_args_parentheses_spec.rb | 30 +++++++++++++++++ 4 files changed, 86 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d89af08ea1e..96bc96b893d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## master (unreleased) +### New features + +* [#6643](https://github.com/rubocop-hq/rubocop/pull/6643): Support `AllowParenthesesInCamelCaseMethod` option on `Style/MethodCallWithArgsParentheses` `omit_parentheses`. ([@dazuma][]) + ## 0.63.1 (2019-01-22) ### Bug fixes @@ -3771,3 +3775,4 @@ [@roooodcastro]: https://github.com/roooodcastro [@rmm5t]: https://github.com/rmm5t [@marcotc]: https://github.com/marcotc +[@dazuma]: https://github.com/dazuma diff --git a/lib/rubocop/cop/style/method_call_with_args_parentheses.rb b/lib/rubocop/cop/style/method_call_with_args_parentheses.rb index 7866036d442..e3927b69fcd 100644 --- a/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +++ b/lib/rubocop/cop/style/method_call_with_args_parentheses.rb @@ -10,7 +10,7 @@ module Style # Additional methods can be added to the `IgnoredMethods` list. This # option is valid only in the default style. # - # In the alternative style (omit_parentheses), there are two additional + # In the alternative style (omit_parentheses), there are three additional # options. # # 1. `AllowParenthesesInChaining` is `false` by default. Setting it to @@ -21,6 +21,12 @@ module Style # to `true` allows the presence of parentheses in multi-line method # calls. # + # 3. `AllowParenthesesInCamelCaseMethod` is `false` by default. This + # allows the presence of parentheses when calling a method whose name + # begins with a capital letter and which has no arguments. Setting it + # to `true` allows the presence of parentheses in such a method call + # even with arguments. + # # @example EnforcedStyle: require_parentheses (default) # # @@ -106,6 +112,22 @@ module Style # # # good # foo().bar 1 + # + # # AllowParenthesesInCamelCaseMethod: false (default) + # + # # bad + # Array(1) + # + # # good + # Array 1 + # + # # AllowParenthesesInCamelCaseMethod: true + # + # # good + # Array(1) + # + # # good + # Array 1 class MethodCallWithArgsParentheses < Cop include ConfigurableEnforcedStyle include IgnoredMethods @@ -155,7 +177,7 @@ def add_offense_for_omit_parentheses(node) return unless node.parenthesized? return if node.implicit_call? return if super_call_without_arguments?(node) - return if camel_case_method_call_without_arguments?(node) + return if allowed_camel_case_method_call?(node) return if legitimate_call_with_parentheses?(node) add_offense(node, location: node.loc.begin.join(node.loc.end)) @@ -221,8 +243,10 @@ def super_call_without_arguments?(node) node.super_type? && node.arguments.none? end - def camel_case_method_call_without_arguments?(node) - node.camel_case_method? && node.arguments.none? + def allowed_camel_case_method_call?(node) + node.camel_case_method? && + (node.arguments.none? || + cop_config['AllowParenthesesInCamelCaseMethod']) end def legitimate_call_with_parentheses?(node) diff --git a/manual/cops_style.md b/manual/cops_style.md index 65e8369c77e..839abb6538a 100644 --- a/manual/cops_style.md +++ b/manual/cops_style.md @@ -2771,7 +2771,7 @@ In the default style (require_parentheses), macro methods are ignored. Additional methods can be added to the `IgnoredMethods` list. This option is valid only in the default style. -In the alternative style (omit_parentheses), there are two additional +In the alternative style (omit_parentheses), there are three additional options. 1. `AllowParenthesesInChaining` is `false` by default. Setting it to @@ -2782,6 +2782,12 @@ options. to `true` allows the presence of parentheses in multi-line method calls. +3. `AllowParenthesesInCamelCaseMethod` is `false` by default. This + allows the presence of parentheses when calling a method whose name + begins with a capital letter and which has no arguments. Setting it + to `true` allows the presence of parentheses in such a method call + even with arguments. + ### Examples #### EnforcedStyle: require_parentheses (default) @@ -2870,6 +2876,22 @@ foo().bar(1) # good foo().bar 1 + +# AllowParenthesesInCamelCaseMethod: false (default) + +# bad +Array(1) + +# good +Array 1 + +# AllowParenthesesInCamelCaseMethod: true + +# good +Array(1) + +# good +Array 1 ``` ### Configurable attributes diff --git a/spec/rubocop/cop/style/method_call_with_args_parentheses_spec.rb b/spec/rubocop/cop/style/method_call_with_args_parentheses_spec.rb index 495c7dd4dcc..0e8d6b3e576 100644 --- a/spec/rubocop/cop/style/method_call_with_args_parentheses_spec.rb +++ b/spec/rubocop/cop/style/method_call_with_args_parentheses_spec.rb @@ -374,6 +374,13 @@ def foo RUBY end + it 'register an offense for camel-case methods with arguments' do + expect_offense(<<-RUBY.strip_indent) + Array(:arg) + ^^^^^^ Omit parentheses for method calls with arguments. + RUBY + end + it 'accepts no parens in method call without args' do expect_no_offenses('top.test') end @@ -558,6 +565,16 @@ def seatle_style arg = default(42) RUBY end + it 'auto-corrects camel-case methods with arguments' do + original = <<-RUBY.strip_indent + Array(:arg) + RUBY + + expect(autocorrect_source(original)).to eq(<<-RUBY.strip_indent) + Array :arg + RUBY + end + context 'TargetRubyVersion >= 2.3', :ruby23 do it 'accepts parens in chaining with safe operators' do expect_no_offenses('Something.find(criteria: given)&.field') @@ -639,5 +656,18 @@ def seatle_style arg = default(42) expect(autocorrect_source(original)).to eq(original) end end + + context 'allowing parens in camel-case methods' do + let(:cop_config) do + { + 'EnforcedStyle' => 'omit_parentheses', + 'AllowParenthesesInCamelCaseMethod' => true + } + end + + it 'accepts parens for camel-case method names' do + expect_no_offenses('Array(nil)') + end + end end end