diff --git a/changelog/change_check_blank_percent_literal.md b/changelog/change_check_blank_percent_literal.md new file mode 100644 index 00000000000..747725d48b4 --- /dev/null +++ b/changelog/change_check_blank_percent_literal.md @@ -0,0 +1 @@ +* [#11130](https://github.com/rubocop/rubocop/pull/11130): Check blank percent literal by `Layout/SpaceInsidePercentLiteralDelimiters`. ([@r7kamura][]) diff --git a/lib/rubocop/cop/layout/space_inside_array_percent_literal.rb b/lib/rubocop/cop/layout/space_inside_array_percent_literal.rb index b764e8f2e37..bc61e07180e 100644 --- a/lib/rubocop/cop/layout/space_inside_array_percent_literal.rb +++ b/lib/rubocop/cop/layout/space_inside_array_percent_literal.rb @@ -6,6 +6,9 @@ module Layout # Checks for unnecessary additional spaces inside array percent literals # (i.e. %i/%w). # + # Note that blank percent literals (e.g. `%i( )`) are checked by + # `Layout/SpaceInsidePercentLiteralDelimiters`. + # # @example # # # bad diff --git a/lib/rubocop/cop/layout/space_inside_percent_literal_delimiters.rb b/lib/rubocop/cop/layout/space_inside_percent_literal_delimiters.rb index 63c67586b80..267e00f27f4 100644 --- a/lib/rubocop/cop/layout/space_inside_percent_literal_delimiters.rb +++ b/lib/rubocop/cop/layout/space_inside_percent_literal_delimiters.rb @@ -8,14 +8,31 @@ module Layout # # @example # + # # bad + # %i( foo bar baz ) + # # # good # %i(foo bar baz) # # # bad # %w( foo bar baz ) # + # # good + # %w(foo bar baz) + # # # bad # %x( ls -l ) + # + # # good + # %x(ls -l) + # + # # bad + # %w( ) + # %w( + # ) + # + # # good + # %w() class SpaceInsidePercentLiteralDelimiters < Base include MatchRange include PercentLiteral @@ -34,11 +51,21 @@ def on_xstr(node) end def on_percent_literal(node) + add_offenses_for_blank_spaces(node) add_offenses_for_unnecessary_spaces(node) end private + def add_offenses_for_blank_spaces(node) + range = body_range(node) + return if range.source.empty? || !range.source.strip.empty? + + add_offense(range) do |corrector| + corrector.remove(range) + end + end + def add_offenses_for_unnecessary_spaces(node) return unless node.single_line? @@ -54,6 +81,13 @@ def regex_matches(node, &blk) each_match_range(contents_range(node), regex, &blk) end end + + def body_range(node) + node.location.expression.with( + begin_pos: node.location.begin.end_pos, + end_pos: node.location.end.begin_pos + ) + end end end end diff --git a/spec/rubocop/cop/layout/space_inside_percent_literal_delimiters_spec.rb b/spec/rubocop/cop/layout/space_inside_percent_literal_delimiters_spec.rb index d2032024e26..e7c997c3c76 100644 --- a/spec/rubocop/cop/layout/space_inside_percent_literal_delimiters_spec.rb +++ b/spec/rubocop/cop/layout/space_inside_percent_literal_delimiters_spec.rb @@ -86,6 +86,36 @@ def foo it 'accepts spaces between entries' do expect_no_offenses(code_example('a b c')) end + + context 'with space in blank percent literals' do + it 'registers and corrects an offense' do + expect_offense(<<~RUBY) + #{code_example(' ')} + ^ #{message} + RUBY + + expect_correction("#{code_example('')}\n") + end + end + + context 'with spaces in blank percent literals' do + it 'registers and corrects an offense' do + expect_offense(<<~RUBY) + #{code_example(' ')} + ^^ #{message} + RUBY + + expect_correction("#{code_example('')}\n") + end + end + + context 'with newline in blank percent literals' do + it 'registers and corrects an offense' do + expect_offense(code_example("\n").lines.insert(1, " ^{} #{message}\n").join) + + expect_correction(code_example('').to_s) + end + end end end end