Skip to content

Commit

Permalink
Update IgnoredMethods so that every cop that uses it will accept bo…
Browse files Browse the repository at this point in the history
…th strings and regexes in the configuration.
  • Loading branch information
dvandersluis authored and bbatsov committed Nov 26, 2020
1 parent 4cc9176 commit c67ecc7
Show file tree
Hide file tree
Showing 15 changed files with 332 additions and 98 deletions.
1 change: 1 addition & 0 deletions changelog/change_update_metricsblocklength_and.md
@@ -1 +1,2 @@
* [#9098](https://github.com/rubocop-hq/rubocop/pull/9098): Update `Metrics/BlockLength` and `Metrics/MethodLength` to use `IgnoredMethods` instead of `ExcludedMethods` in configuration. The previous key is retained for backwards compatibility. ([@dvandersluis][])
* [#9098](https://github.com/rubocop-hq/rubocop/pull/9098): Update `IgnoredMethods` so that every cop that uses it will accept both strings and regexes in the configuration. ([@dvandersluis][])
7 changes: 5 additions & 2 deletions lib/rubocop/cop/metrics/block_length.rb
Expand Up @@ -44,19 +44,22 @@ class BlockLength < Base
LABEL = 'Block'

def on_block(node)
return if excluded_method?(node)
return if ignored_method?(node.method_name)
return if method_receiver_excluded?(node)
return if node.class_constructor? || node.struct_constructor?

check_code_length(node)
end

private

def excluded_method?(node)
def method_receiver_excluded?(node)
node_receiver = node.receiver&.source&.gsub(/\s+/, '')
node_method = String(node.method_name)

ignored_methods.any? do |config|
next unless config.is_a?(String)

receiver, method = config.split('.')

unless method
Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/metrics/method_length.rb
Expand Up @@ -41,7 +41,7 @@ class MethodLength < Base
LABEL = 'Method'

def on_def(node)
return if ignored_methods.any? { |m| m.match? String(node.method_name) }
return if ignored_method?(node.method_name)

check_code_length(node)
end
Expand Down
11 changes: 10 additions & 1 deletion lib/rubocop/cop/mixin/ignored_methods.rb
Expand Up @@ -4,6 +4,8 @@ module RuboCop
module Cop
# This module encapsulates the ability to ignore certain methods when
# parsing.
# Cops that use `IgnoredMethods` can accept either strings or regexes to match
# against.
module IgnoredMethods
# Configuration for IgnoredMethods. It is added to classes that include
# the module so that configuration can be set using the `ignored_methods`
Expand All @@ -21,7 +23,14 @@ def self.included(base)
end

def ignored_method?(name)
ignored_methods.include?(name.to_s)
ignored_methods.any? do |value|
case value
when Regexp
value.match? String(name)
else
value == String(name)
end
end
end

def ignored_methods
Expand Down
6 changes: 6 additions & 0 deletions lib/rubocop/cop/mixin/method_complexity.rb
Expand Up @@ -11,6 +11,12 @@ module MethodComplexity
include Metrics::Utils::RepeatedCsendDiscount
extend NodePattern::Macros

# Ensure cops that include `MethodComplexity` have the config
# `attr_accessor`s that `ignored_method?` needs.
def self.included(base)
base.extend(IgnoredMethods::Config)
end

def on_def(node)
return if ignored_method?(node.method_name)

Expand Down
45 changes: 32 additions & 13 deletions spec/rubocop/cop/lint/number_conversion_spec.rb
Expand Up @@ -158,19 +158,38 @@
end

context 'IgnoredMethods' do
let(:cop_config) { { 'IgnoredMethods' => %w[minutes] } }

it 'does not register an offense for an ignored method' do
expect_no_offenses(<<~RUBY)
10.minutes.to_i
RUBY
end

it 'registers an offense for other methods' do
expect_offense(<<~RUBY)
10.hours.to_i
^^^^^^^^^^^^^ Replace unsafe number conversion with number class parsing, instead of using 10.hours.to_i, use stricter Integer(10.hours, 10).
RUBY
context 'with a string' do
let(:cop_config) { { 'IgnoredMethods' => %w[minutes] } }

it 'does not register an offense for an ignored method' do
expect_no_offenses(<<~RUBY)
10.minutes.to_i
RUBY
end

it 'registers an offense for other methods' do
expect_offense(<<~RUBY)
10.hours.to_i
^^^^^^^^^^^^^ Replace unsafe number conversion with number class parsing, instead of using 10.hours.to_i, use stricter Integer(10.hours, 10).
RUBY
end
end

context 'with a regex' do
let(:cop_config) { { 'IgnoredMethods' => [/minutes/] } }

it 'does not register an offense for an ignored method' do
expect_no_offenses(<<~RUBY)
10.minutes.to_i
RUBY
end

it 'registers an offense for other methods' do
expect_offense(<<~RUBY)
10.hours.to_i
^^^^^^^^^^^^^ Replace unsafe number conversion with number class parsing, instead of using 10.hours.to_i, use stricter Integer(10.hours, 10).
RUBY
end
end
end
end
70 changes: 50 additions & 20 deletions spec/rubocop/cop/metrics/abc_size_spec.rb
Expand Up @@ -78,30 +78,60 @@ def method_name
end

context 'when method is in list of ignored methods' do
let(:cop_config) { { 'Max' => 0, 'IgnoredMethods' => ['foo'] } }
context 'when given a string' do
let(:cop_config) { { 'Max' => 0, 'IgnoredMethods' => ['foo'] } }

it 'does not register an offense when defining an instance method' do
expect_no_offenses(<<~RUBY)
def foo
bar.baz(:qux)
end
RUBY
end

it 'does not register an offense when defining an instance method' do
expect_no_offenses(<<~RUBY)
def foo
bar.baz(:qux)
end
RUBY
end
it 'does not register an offense when defining a class method' do
expect_no_offenses(<<~RUBY)
def self.foo
bar.baz(:qux)
end
RUBY
end

it 'does not register an offense when defining a class method' do
expect_no_offenses(<<~RUBY)
def self.foo
bar.baz(:qux)
end
RUBY
it 'does not register an offense when using `define_method`' do
expect_no_offenses(<<~RUBY)
define_method :foo do
bar.baz(:qux)
end
RUBY
end
end

it 'does not register an offense when using `define_method`' do
expect_no_offenses(<<~RUBY)
define_method :foo do
bar.baz(:qux)
end
RUBY
context 'when given a regex' do
let(:cop_config) { { 'Max' => 0, 'IgnoredMethods' => [/foo/] } }

it 'does not register an offense when defining an instance method' do
expect_no_offenses(<<~RUBY)
def foo
bar.baz(:qux)
end
RUBY
end

it 'does not register an offense when defining a class method' do
expect_no_offenses(<<~RUBY)
def self.foo
bar.baz(:qux)
end
RUBY
end

it 'does not register an offense when using `define_method`' do
expect_no_offenses(<<~RUBY)
define_method :foo do
bar.baz(:qux)
end
RUBY
end
end
end
end
Expand Down
27 changes: 27 additions & 0 deletions spec/rubocop/cop/metrics/block_length_spec.rb
Expand Up @@ -249,5 +249,32 @@ def foo
end
end
end

context 'when given a regex' do
before { cop_config['IgnoredMethods'] = [/baz/] }

it 'does not report an offense' do
expect_no_offenses(<<~RUBY)
Foo::Bar.baz do
a = 1
a = 2
a = 3
end
RUBY
end

context 'that does not match' do
it 'reports an offense' do
expect_offense(<<~RUBY)
Foo::Bar.bar do
^^^^^^^^^^^^^^^ Block has too many lines. [3/2]
a = 1
a = 2
a = 3
end
RUBY
end
end
end
end
end
72 changes: 51 additions & 21 deletions spec/rubocop/cop/metrics/cyclomatic_complexity_spec.rb
Expand Up @@ -292,31 +292,61 @@ def method_name_2
end
end

context 'when method is in list of ignored methods' do
let(:cop_config) { { 'Max' => 0, 'IgnoredMethods' => ['foo'] } }
context 'when IgnoredMethods is set' do
context 'with a string' do
let(:cop_config) { { 'Max' => 0, 'IgnoredMethods' => ['foo'] } }

it 'does not register an offense when defining an instance method' do
expect_no_offenses(<<~RUBY)
def foo
bar.baz(:qux)
end
RUBY
end

it 'does not register an offense when defining an instance method' do
expect_no_offenses(<<~RUBY)
def foo
bar.baz(:qux)
end
RUBY
end
it 'does not register an offense when defining a class method' do
expect_no_offenses(<<~RUBY)
def self.foo
bar.baz(:qux)
end
RUBY
end

it 'does not register an offense when defining a class method' do
expect_no_offenses(<<~RUBY)
def self.foo
bar.baz(:qux)
end
RUBY
it 'does not register an offense when using `define_method`' do
expect_no_offenses(<<~RUBY)
define_method :foo do
bar.baz(:qux)
end
RUBY
end
end

it 'does not register an offense when using `define_method`' do
expect_no_offenses(<<~RUBY)
define_method :foo do
bar.baz(:qux)
end
RUBY
context 'with a regex' do
let(:cop_config) { { 'Max' => 0, 'IgnoredMethods' => [/foo/] } }

it 'does not register an offense when defining an instance method' do
expect_no_offenses(<<~RUBY)
def foo
bar.baz(:qux)
end
RUBY
end

it 'does not register an offense when defining a class method' do
expect_no_offenses(<<~RUBY)
def self.foo
bar.baz(:qux)
end
RUBY
end

it 'does not register an offense when using `define_method`' do
expect_no_offenses(<<~RUBY)
define_method :foo do
bar.baz(:qux)
end
RUBY
end
end
end

Expand Down

0 comments on commit c67ecc7

Please sign in to comment.