Skip to content

Commit

Permalink
Merge pull request #8271 from fatkodima/hash-array-last-item
Browse files Browse the repository at this point in the history
Add new `Style/HashArrayLastItem` cop
  • Loading branch information
koic committed Jul 9, 2020
2 parents 9f4382c + b307d03 commit ad4d557
Show file tree
Hide file tree
Showing 7 changed files with 193 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -5,6 +5,7 @@
### New features

* [#8242](https://github.com/rubocop-hq/rubocop/pull/8242): Internal profiling available with `bin/rubocop-profile` and rake tasks. ([@marcandre][])
* [#4286](https://github.com/rubocop-hq/rubocop/issues/4286): Add new `Style/HashAsLastArrayItem` cop. ([@fatkodima][])

### Bug fixes

Expand Down
12 changes: 12 additions & 0 deletions config/default.yml
Expand Up @@ -2961,6 +2961,18 @@ Style/GuardClause:
# needs to have to trigger this cop
MinBodyLength: 1

Style/HashAsLastArrayItem:
Description: >-
Checks for presence or absence of braces around hash literal as a last
array item depending on configuration.
StyleGuide: '#hash-literal-as-last-array-item'
Enabled: 'pending'
VersionAdded: '0.88'
EnforcedStyle: braces
SupportedStyles:
- braces
- no_braces

Style/HashEachMethods:
Description: 'Use Hash#each_key and Hash#each_value.'
StyleGuide: '#hash-each'
Expand Down
1 change: 1 addition & 0 deletions docs/modules/ROOT/pages/cops.adoc
Expand Up @@ -369,6 +369,7 @@ In the following section you find all available cops:
* xref:cops_style.adoc#stylefrozenstringliteralcomment[Style/FrozenStringLiteralComment]
* xref:cops_style.adoc#styleglobalvars[Style/GlobalVars]
* xref:cops_style.adoc#styleguardclause[Style/GuardClause]
* xref:cops_style.adoc#stylehashaslastarrayitem[Style/HashAsLastArrayItem]
* xref:cops_style.adoc#stylehasheachmethods[Style/HashEachMethods]
* xref:cops_style.adoc#stylehashsyntax[Style/HashSyntax]
* xref:cops_style.adoc#stylehashtransformkeys[Style/HashTransformKeys]
Expand Down
53 changes: 53 additions & 0 deletions docs/modules/ROOT/pages/cops_style.adoc
Expand Up @@ -3354,6 +3354,59 @@ ok

* https://rubystyle.guide#no-nested-conditionals

== Style/HashAsLastArrayItem

|===
| Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged

| Pending
| Yes
| Yes
| 0.88
| -
|===

Checks for presence or absence of braces around hash literal as a last
array item depending on configuration.

=== Examples

==== EnforcedStyle: braces (default)

[source,ruby]
----
# bad
[1, 2, one: 1, two: 2]
# good
[1, 2, { one: 1, two: 2 }]
----

==== EnforcedStyle: no_braces

[source,ruby]
----
# bad
[1, 2, { one: 1, two: 2 }]
# good
[1, 2, one: 1, two: 2]
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| EnforcedStyle
| `braces`
| `braces`, `no_braces`
|===

=== References

* https://rubystyle.guide#hash-literal-as-last-array-item

== Style/HashEachMethods

|===
Expand Down
1 change: 1 addition & 0 deletions lib/rubocop.rb
Expand Up @@ -413,6 +413,7 @@
require_relative 'rubocop/cop/style/frozen_string_literal_comment'
require_relative 'rubocop/cop/style/global_vars'
require_relative 'rubocop/cop/style/guard_clause'
require_relative 'rubocop/cop/style/hash_as_last_array_item'
require_relative 'rubocop/cop/style/hash_each_methods'
require_relative 'rubocop/cop/style/hash_syntax'
require_relative 'rubocop/cop/style/hash_transform_keys'
Expand Down
62 changes: 62 additions & 0 deletions lib/rubocop/cop/style/hash_as_last_array_item.rb
@@ -0,0 +1,62 @@
# frozen_string_literal: true

module RuboCop
module Cop
module Style
# Checks for presence or absence of braces around hash literal as a last
# array item depending on configuration.
#
# @example EnforcedStyle: braces (default)
# # bad
# [1, 2, one: 1, two: 2]
#
# # good
# [1, 2, { one: 1, two: 2 }]
#
# @example EnforcedStyle: no_braces
# # bad
# [1, 2, { one: 1, two: 2 }]
#
# # good
# [1, 2, one: 1, two: 2]
#
class HashAsLastArrayItem < Base
include ConfigurableEnforcedStyle
extend AutoCorrector

def on_hash(node)
return unless node.parent&.array_type?

if braces_style?
check_braces(node)
else
check_no_braces(node)
end
end

private

def check_braces(node)
return if node.braces?

add_offense(node, message: 'Wrap hash in `{` and `}`.') do |corrector|
corrector.wrap(node, '{', '}')
end
end

def check_no_braces(node)
return unless node.braces?

add_offense(node, message: 'Omit the braces around the hash.') do |corrector|
corrector.remove(node.loc.begin)
corrector.remove(node.loc.end)
end
end

def braces_style?
style == :braces
end
end
end
end
end
63 changes: 63 additions & 0 deletions spec/rubocop/cop/style/hash_as_last_array_item_spec.rb
@@ -0,0 +1,63 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::Style::HashAsLastArrayItem, :config do
subject(:cop) { described_class.new(config) }

context 'when EnforcedStyle is braces' do
let(:cop_config) do
{ 'EnforcedStyle' => 'braces' }
end

it 'registers an offense and corrects when hash without braces' do
expect_offense(<<~RUBY)
[1, 2, one: 1, two: 2]
^^^^^^^^^^^^^^ Wrap hash in `{` and `}`.
RUBY

expect_correction(<<~RUBY)
[1, 2, {one: 1, two: 2}]
RUBY
end

it 'does not register an offense when hash with braces' do
expect_no_offenses(<<~RUBY)
[1, 2, { one: 1, two: 2 }]
RUBY
end

it 'does not register an offense when hash is not inside array' do
expect_no_offenses(<<~RUBY)
foo(one: 1, two: 2)
RUBY
end
end

context 'when EnforcedStyle is no_braces' do
let(:cop_config) do
{ 'EnforcedStyle' => 'no_braces' }
end

it 'registers an offense and corrects when hash with braces' do
expect_offense(<<~RUBY)
[1, 2, { one: 1, two: 2 }]
^^^^^^^^^^^^^^^^^^ Omit the braces around the hash.
RUBY

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

it 'does not register an offense when hash without braces' do
expect_no_offenses(<<~RUBY)
[1, 2, one: 1, two: 2]
RUBY
end

it 'does not register an offense when hash is not inside array' do
expect_no_offenses(<<~RUBY)
foo({ one: 1, two: 2 })
RUBY
end
end
end

0 comments on commit ad4d557

Please sign in to comment.