Skip to content

Commit

Permalink
[Fix rubocop#9962] Update Style/WordArray to register an offense in…
Browse files Browse the repository at this point in the history
… `percent` style if any values contain spaces.
  • Loading branch information
dvandersluis committed Aug 4, 2021
1 parent 52805b6 commit 4f76885
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 10 deletions.
1 change: 1 addition & 0 deletions changelog/change_update_stylewordarray_to_register_an.md
@@ -0,0 +1 @@
* [#9962](https://github.com/rubocop/rubocop/issues/9962): Update `Style/WordArray` to register an offense in `percent` style if any values contain spaces. ([@dvandersluis][])
2 changes: 1 addition & 1 deletion config/default.yml
Expand Up @@ -4921,7 +4921,7 @@ Style/WordArray:
StyleGuide: '#percent-w'
Enabled: true
VersionAdded: '0.9'
VersionChanged: '0.36'
VersionChanged: '<<next>>'
EnforcedStyle: percent
SupportedStyles:
# percent style: %w(word1 word2)
Expand Down
17 changes: 10 additions & 7 deletions lib/rubocop/cop/mixin/percent_array.rb
Expand Up @@ -18,15 +18,16 @@ def invalid_percent_array_context?(node)
!parent.parenthesized? && parent&.block_literal?
end

# Override to determine values that are invalid in a percent array
def invalid_percent_array_contents?(_node)
false
end

def allowed_bracket_array?(node)
comments_in_array?(node) || below_array_length?(node) ||
invalid_percent_array_context?(node)
end

def message(_node)
style == :percent ? self.class::PERCENT_MSG : self.class::ARRAY_MSG
end

def comments_in_array?(node)
line_span = node.source_range.first_line...node.source_range.last_line
processed_source.each_comment_in_lines(line_span).any?
Expand All @@ -35,9 +36,11 @@ def comments_in_array?(node)
def check_percent_array(node)
array_style_detected(:percent, node.values.size)

return unless style == :brackets
return unless style == :brackets || invalid_percent_array_contents?(node)

add_offense(node) { |corrector| correct_bracketed(corrector, node) }
add_offense(node, message: self.class::ARRAY_MSG) do |corrector|
correct_bracketed(corrector, node)
end
end

def check_bracketed_array(node, literal_prefix)
Expand All @@ -47,7 +50,7 @@ def check_bracketed_array(node, literal_prefix)

return unless style == :percent

add_offense(node) do |corrector|
add_offense(node, message: self.class::PERCENT_MSG) do |corrector|
percent_literal_corrector = PercentLiteralCorrector.new(@config, @preferred_delimiters)
percent_literal_corrector.correct(corrector, node, literal_prefix)
end
Expand Down
22 changes: 20 additions & 2 deletions lib/rubocop/cop/style/word_array.rb
Expand Up @@ -9,6 +9,9 @@ module Style
# Alternatively, it can check for uses of the %w() syntax, in projects
# which do not want to include that syntax.
#
# NOTE: When using the `percent` style, %w() arrays containing a space
# will be registered as offenses.
#
# Configuration option: MinSize
# If set, arrays with fewer elements than this value will not trigger the
# cop. For example, a `MinSize` of `3` will not enforce a style on an
Expand All @@ -21,12 +24,18 @@ module Style
# # bad
# ['foo', 'bar', 'baz']
#
# # bad (contains spaces)
# %w[foo\ bar baz\ quux]
#
# @example EnforcedStyle: brackets
# # good
# ['foo', 'bar', 'baz']
#
# # bad
# %w[foo bar baz]
#
# # good (contains spaces)
# ['foo bar', 'baz quux']
class WordArray < Base
include ArrayMinSize
include ArraySyntax
Expand All @@ -53,13 +62,22 @@ def on_array(node)

private

def complex_content?(strings)
def complex_content?(strings, complex_regex: word_regex)
strings.any? do |s|
next unless s.str_content

string = s.str_content.dup.force_encoding(::Encoding::UTF_8)
!string.valid_encoding? || !word_regex.match?(string) || / /.match?(string)
!string.valid_encoding? ||
(complex_regex && !complex_regex.match?(string)) ||
/ /.match?(string)
end
end

def invalid_percent_array_contents?(node)
# Disallow %w() arrays that contain invalid encoding or spaces
complex_content?(node.values, complex_regex: false)
end

def word_regex
Regexp.new(cop_config['WordRegex'])
end
Expand Down
32 changes: 32 additions & 0 deletions spec/rubocop/cop/style/word_array_spec.rb
Expand Up @@ -317,6 +317,34 @@
_investigate(cop2, parse_source('%w(a b c)'))
expect(cop2.config_to_allow_offenses).to eq('EnforcedStyle' => 'percent', 'MinSize' => 3)
end

it 'registers an offense for a %w() array containing spaces' do
expect_offense(<<~'RUBY')
%w(one\ two three\ four)
^^^^^^^^^^^^^^^^^^^^^^^^ Use `[]` for an array of words.
RUBY

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

it 'does not register an offense for a %w() array containing non word characters' do
expect_no_offenses(<<~RUBY)
%w(% %i %I %q %Q %r %s %w %W %x)
RUBY
end

it 'corrects properly when there is an extra trailing comma' do
expect_offense(<<~RUBY)
A = ["one", "two",]
^^^^^^^^^^^^^^^ Use `%w` or `%W` for an array of words.
RUBY

expect_correction(<<~RUBY)
A = %w(one two)
RUBY
end
end

context 'when EnforcedStyle is array' do
Expand All @@ -338,6 +366,10 @@
expect_no_offenses("['foo', 'bar', 'foo-bar']")
end

it 'does not register an offense for arrays of strings with spaces' do
expect_no_offenses("['foo bar', 'baz quux']")
end

it 'registers an offense for a %w() array' do
expect_offense(<<~RUBY)
%w(one two three)
Expand Down

0 comments on commit 4f76885

Please sign in to comment.