Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Fix #7492] Add Style/TrailingCommaInBlockArgs
- Loading branch information
Showing
7 changed files
with
284 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
# frozen_string_literal: true | ||
|
||
module RuboCop | ||
module Cop | ||
module Style | ||
# This cop checks whether trailing commas in block arguments are | ||
# required. Blocks with only one argument and a trailing comma require | ||
# that comma to be present. Blocks with more than one argument never | ||
# require a trailing comma. | ||
# | ||
# @example | ||
# # bad | ||
# add { |foo, bar,| foo + bar } | ||
# | ||
# # good | ||
# add { |foo, bar| foo + bar } | ||
# | ||
# # good | ||
# add { |foo,| foo } | ||
# | ||
# # good | ||
# add { foo } | ||
# | ||
# # bad | ||
# add do |foo, bar,| | ||
# foo + bar | ||
# end | ||
# | ||
# # good | ||
# add do |foo, bar| | ||
# foo + bar | ||
# end | ||
# | ||
# # good | ||
# add do |foo,| | ||
# foo | ||
# end | ||
# | ||
# # good | ||
# add do | ||
# foo + bar | ||
# end | ||
class TrailingCommaInBlockArgs < Cop | ||
MSG = 'Useless trailing comma present in block arguments.' | ||
|
||
def on_block(node) | ||
return unless useless_trailing_comma?(node) | ||
|
||
add_offense(node, location: last_comma(node).pos) | ||
end | ||
|
||
def autocorrect(node) | ||
->(corrector) { corrector.replace(last_comma(node).pos, '') } | ||
end | ||
|
||
private | ||
|
||
def useless_trailing_comma?(node) | ||
arg_count(node) > 1 && trailing_comma?(node) | ||
end | ||
|
||
def arg_count(node) | ||
node.arguments.each_descendant(:arg, :optarg, :kwoptarg).to_a.size | ||
end | ||
|
||
def trailing_comma?(node) | ||
argument_tokens(node).last.comma? | ||
end | ||
|
||
def last_comma(node) | ||
argument_tokens(node).last | ||
end | ||
|
||
def argument_tokens(node) | ||
pipes = tokens(node).select { |token| token.type == :tPIPE } | ||
begin_pos, end_pos = pipes.map do |pipe| | ||
tokens(node).index(pipe) | ||
end | ||
|
||
tokens(node)[begin_pos + 1..end_pos - 1] | ||
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
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
142 changes: 142 additions & 0 deletions
142
spec/rubocop/cop/style/trailing_comma_in_block_args_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,142 @@ | ||
# frozen_string_literal: true | ||
|
||
RSpec.describe RuboCop::Cop::Style::TrailingCommaInBlockArgs do | ||
subject(:cop) { described_class.new(config) } | ||
|
||
let(:config) { RuboCop::Config.new } | ||
|
||
context 'curly brace block format' do | ||
it 'registers an offense when a trailing comma is not needed' do | ||
expect_offense(<<~RUBY) | ||
test { |a, b,| a + b } | ||
^ Useless trailing comma present in block arguments. | ||
RUBY | ||
expect_correction(<<~RUBY) | ||
test { |a, b| a + b } | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense when a trailing comma is required' do | ||
expect_no_offenses(<<~RUBY) | ||
test { |a,| a } | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense when no arguments are present' do | ||
expect_no_offenses(<<~RUBY) | ||
test { a } | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense when more than one argument is ' \ | ||
'present with no trailing comma' do | ||
expect_no_offenses(<<~RUBY) | ||
test { |a, b| a + b } | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense for default arguments' do | ||
expect_no_offenses(<<~RUBY) | ||
test { |a, b, c = nil| a + b + c } | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense for keyword arguments' do | ||
expect_no_offenses(<<~RUBY) | ||
test { |a, b, c: 1| a + b + c } | ||
RUBY | ||
end | ||
|
||
it 'ignores commas in default argument strings' do | ||
expect_no_offenses(<<~RUBY) | ||
add { |foo, bar = ','| foo + bar } | ||
RUBY | ||
end | ||
|
||
it 'preserves semicolons in block/local variables' do | ||
expect_no_offenses(<<~RUBY) | ||
add { |foo, bar,; baz| foo + bar } | ||
RUBY | ||
end | ||
end | ||
|
||
context 'do/end block format' do | ||
it 'registers an offense when a trailing comma is not needed' do | ||
expect_offense(<<~RUBY) | ||
test do |a, b,| | ||
^ Useless trailing comma present in block arguments. | ||
a + b | ||
end | ||
RUBY | ||
expect_correction(<<~RUBY) | ||
test do |a, b| | ||
a + b | ||
end | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense when a trailing comma is required' do | ||
expect_no_offenses(<<~RUBY) | ||
test do |a,| | ||
a | ||
end | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense when no arguments are present' do | ||
expect_no_offenses(<<~RUBY) | ||
test do | ||
a | ||
end | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense for an empty block' do | ||
expect_no_offenses(<<~RUBY) | ||
test do || | ||
end | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense when more than one argument is ' \ | ||
'present with no trailing comma' do | ||
expect_no_offenses(<<~RUBY) | ||
test do |a, b| | ||
a + b | ||
end | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense for default arguments' do | ||
expect_no_offenses(<<~RUBY) | ||
test do |a, b, c = nil| | ||
a + b + c | ||
end | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense for keyword arguments' do | ||
expect_no_offenses(<<~RUBY) | ||
test do |a, b, c: 1| | ||
a + b + c | ||
end | ||
RUBY | ||
end | ||
|
||
it 'ignores commas in default argument strings' do | ||
expect_no_offenses(<<~RUBY) | ||
add do |foo, bar = ','| | ||
foo + bar | ||
end | ||
RUBY | ||
end | ||
|
||
it 'preserves semicolons in block/local variables' do | ||
expect_no_offenses(<<~RUBY) | ||
add do |foo, bar,; baz| | ||
foo + bar | ||
end | ||
RUBY | ||
end | ||
end | ||
end |