Skip to content

Commit

Permalink
[Fix #11802] Improve handling of delimiters with percent style symbol…
Browse files Browse the repository at this point in the history
… arrays
  • Loading branch information
jasondoc3 committed Jul 21, 2023
1 parent 3bf6d41 commit 80acfbd
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 25 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* [#11802](https://github.com/rubocop/rubocop/issues/11802): Improve handling of `[]` and `()` with percent symbol arrays. ([@jasondoc3][])
25 changes: 22 additions & 3 deletions lib/rubocop/cop/style/symbol_array.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ module Style
# # bad
# [:foo, :bar, :baz]
#
# # bad (contains spaces)
# %i[foo\ bar baz\ quux]
#
# # bad (contains [] with spaces)
# %i[foo \[ \]]
#
# # bad (contains () with spaces)
# %i(foo \( \))
#
# @example EnforcedStyle: brackets
# # good
# [:foo, :bar, :baz]
Expand All @@ -40,14 +49,15 @@ class SymbolArray < Base

PERCENT_MSG = 'Use `%i` or `%I` for an array of symbols.'
ARRAY_MSG = 'Use %<prefer>s for an array of symbols.'
DELIMITERS = ['[', ']', '(', ')'].freeze

class << self
attr_accessor :largest_brackets
end

def on_array(node)
if bracketed_array_of?(:sym, node)
return if symbols_contain_spaces?(node)
return if complex_content?(node)

check_bracketed_array(node, 'i')
elsif node.percent_literal?(:symbol)
Expand All @@ -57,13 +67,22 @@ def on_array(node)

private

def symbols_contain_spaces?(node)
def complex_content?(node)
node.children.any? do |sym|
content, = *sym
content.to_s.include?(' ')
content = content.to_s
content_without_delimiter_pairs = content.gsub(/(\[\])|(\(\))/, '')

content.include?(' ') || DELIMITERS.any? do |delimiter|
content_without_delimiter_pairs.include?(delimiter)
end
end
end

def invalid_percent_array_contents?(node)
complex_content?(node)
end

def build_bracketed_array(node)
return '[]' if node.children.empty?

Expand Down
56 changes: 34 additions & 22 deletions spec/rubocop/cop/style/symbol_array_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -79,17 +79,6 @@
RUBY
end

it "doesn't break when a symbol contains )" do
expect_offense(<<~RUBY)
[:one, :")", :three, :"(", :"]", :"["]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `%i` or `%I` for an array of symbols.
RUBY

expect_correction(<<~'RUBY')
%i(one \) three \( ] [)
RUBY
end

it 'does not register an offense for array with non-syms' do
expect_no_offenses('[:one, :two, "three"]')
end
Expand All @@ -98,10 +87,22 @@
expect_no_offenses('%i(one two three)')
end

it 'does not register an offense for array containing delimiters without spaces' do
expect_no_offenses('%i[one two [] ()]')
end

it 'does not register an offense if symbol contains whitespace' do
expect_no_offenses('[:one, :two, :"space here"]')
end

it 'does not register an offense if a symbol contains unclosed delimiters' do
expect_no_offenses('[:one, :")", :two, :"(", :"]"]')
end

it 'does not register an offense if a symbol contains a delimiter with spaces' do
expect_no_offenses('[:one, :two, :"[ ]", :"( )"]')
end

it 'registers an offense in a non-ambiguous block context' do
expect_offense(<<~RUBY)
foo([:bar, :baz]) { qux }
Expand Down Expand Up @@ -133,6 +134,28 @@
expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
end

it 'registers an offense for a %i array containing [ ]' do
expect_offense(<<~'RUBY')
%i[one \[ \] two]
^^^^^^^^^^^^^^^^^ Use `[:one, :'[', :']', :two]` for an array of symbols.
RUBY

expect_correction(<<~RUBY)
[:one, :'[', :']', :two]
RUBY
end

it 'registers an offense for a %i array containing ( )' do
expect_offense(<<~'RUBY')
%i(one \( \) two)
^^^^^^^^^^^^^^^^^ Use `[:one, :'(', :')', :two]` for an array of symbols.
RUBY

expect_correction(<<~RUBY)
[:one, :'(', :')', :two]
RUBY
end

context 'when PreferredDelimiters is specified' do
let(:other_cops) do
{
Expand All @@ -144,17 +167,6 @@
}
end

it 'autocorrects an array with delimiters' do
expect_offense(<<~RUBY)
[:one, :")", :three, :"(", :"]", :"["]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `%i` or `%I` for an array of symbols.
RUBY

expect_correction(<<~'RUBY')
%i[one ) three ( \] \[]
RUBY
end

it 'autocorrects an array in multiple lines' do
expect_offense(<<-RUBY)
[
Expand Down

0 comments on commit 80acfbd

Please sign in to comment.