-
-
Notifications
You must be signed in to change notification settings - Fork 83
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add new
Performance/BlockGivenWithExplicitBlock
cop
- Loading branch information
Showing
7 changed files
with
177 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
56 changes: 56 additions & 0 deletions
56
lib/rubocop/cop/performance/block_given_with_explicit_block.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
# frozen_string_literal: true | ||
|
||
module RuboCop | ||
module Cop | ||
module Performance | ||
# This cop identifies unnecessary use of a `block_given?` where explicit check | ||
# of block argument would suffice. | ||
# | ||
# @example | ||
# # bad | ||
# def method(&block) | ||
# do_something if block_given? | ||
# end | ||
# | ||
# # good | ||
# def method(&block) | ||
# do_something if block | ||
# end | ||
# | ||
# # good - block is reassigned | ||
# def method(&block) | ||
# block ||= -> { do_something } | ||
# warn "Using default ..." unless block_given? | ||
# # ... | ||
# end | ||
# | ||
class BlockGivenWithExplicitBlock < Base | ||
extend AutoCorrector | ||
|
||
RESTRICT_ON_SEND = %i[block_given?].freeze | ||
MSG = 'Check block argument explicitly instead of using `block_given?`.' | ||
|
||
def on_send(node) | ||
def_node = node.each_ancestor(:def, :defs).first | ||
return unless def_node | ||
|
||
block_arg = def_node.arguments.find(&:blockarg_type?) | ||
return unless block_arg | ||
|
||
block_arg_name = block_arg.source[1..-1].to_sym | ||
return if reassigns_block_arg?(def_node, block_arg_name) | ||
|
||
add_offense(node) do |corrector| | ||
corrector.replace(node, block_arg_name) | ||
end | ||
end | ||
|
||
private | ||
|
||
def reassigns_block_arg?(def_node, block_arg_name) | ||
def_node.each_descendant(:lvasgn).any? { |node| node.children[0] == block_arg_name } | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
73 changes: 73 additions & 0 deletions
73
spec/rubocop/cop/performance/block_given_with_explicit_block_spec.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
# frozen_string_literal: true | ||
|
||
RSpec.describe RuboCop::Cop::Performance::BlockGivenWithExplicitBlock do | ||
subject(:cop) { described_class.new } | ||
|
||
it 'registers an offense and corrects when using `block_given?` in an instance method with block arg' do | ||
expect_offense(<<~RUBY) | ||
def method(x, &block) | ||
do_something if block_given? | ||
^^^^^^^^^^^^ Check block argument explicitly instead of using `block_given?`. | ||
end | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
def method(x, &block) | ||
do_something if block | ||
end | ||
RUBY | ||
end | ||
|
||
it 'registers an offense and corrects when using `block_given?` in a class method with block arg' do | ||
expect_offense(<<~RUBY) | ||
def self.method(x, &block) | ||
do_something if block_given? | ||
^^^^^^^^^^^^ Check block argument explicitly instead of using `block_given?`. | ||
end | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
def self.method(x, &block) | ||
do_something if block | ||
end | ||
RUBY | ||
end | ||
|
||
it 'registers an offense and corrects when using `block_given?` in a method with non standard block arg name' do | ||
expect_offense(<<~RUBY) | ||
def method(x, &myblock) | ||
do_something if block_given? | ||
^^^^^^^^^^^^ Check block argument explicitly instead of using `block_given?`. | ||
end | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
def method(x, &myblock) | ||
do_something if myblock | ||
end | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense when using `block_given?` in a method without block arg' do | ||
expect_no_offenses(<<~RUBY) | ||
def method(x) | ||
do_something if block_given? | ||
end | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense when block arg is reassigned' do | ||
expect_no_offenses(<<~RUBY) | ||
def method(a, &block) | ||
block ||= -> {} | ||
do_something if block_given? | ||
end | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense when `block_given?` is used outside of a method' do | ||
expect_no_offenses(<<~RUBY) | ||
do_something if block_given? | ||
RUBY | ||
end | ||
end |