Skip to content

Commit

Permalink
[Fix #7976] Add ignore options for `Layout/EmptyLinesAroundAttributeA…
Browse files Browse the repository at this point in the history
…ccessor`

Fixes #7976 and #7981

This PR adds `AllowAliasSyntax` and `AllowedMethods` options.
for `Layout/EmptyLinesAroundAttributeAccessor` cop.

Users can configure a behavior for `alias` syntax using
`IgnoreAliasSyntax` option. Ignored by default (true).

And users can specify ignored methods using `AllowedMethods`.
By default, set `alias_method`, `public`, `protected`, and
`private` provided by Ruby.

`cattr_accessor`, `attribute`, other methods provided by Rails (and other gems)
can be set by user applications or RuboCop Rails gem.
  • Loading branch information
koic authored and bbatsov committed May 17, 2020
1 parent 4d102d6 commit fdbbda2
Show file tree
Hide file tree
Showing 5 changed files with 186 additions and 9 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -6,6 +6,7 @@

* [#7735](https://github.com/rubocop-hq/rubocop/issues/7735): `NodePattern` and `AST` classes have been moved to the [`rubocop-ast` gem](https://github.com/rubocop-hq/rubocop-ast). ([@marcandre][])
* [#7950](https://github.com/rubocop-hq/rubocop/pull/7950): Add new `Lint/DeprecatedOpenSSLConstant` cop. ([@bdewater][])
* [#7976](https://github.com/rubocop-hq/rubocop/issues/7976): Add `IgnoreAliasSyntax` and` IgnoredMethods` options for `Layout/EmptyLinesAroundAttributeAccessor`. ([@koic][])

### Bug fixes

Expand Down
7 changes: 7 additions & 0 deletions config/default.yml
Expand Up @@ -468,6 +468,13 @@ Layout/EmptyLinesAroundAttributeAccessor:
StyleGuide: '#empty-lines-around-attribute-accessor'
Enabled: pending
VersionAdded: '0.83'
VersionChanged: '0.84'
AllowAliasSyntax: true
AllowedMethods:
- alias_method
- public
- protected
- private

Layout/EmptyLinesAroundBeginBody:
Description: "Keeps track of empty lines around begin-end bodies."
Expand Down
60 changes: 56 additions & 4 deletions lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb
Expand Up @@ -3,7 +3,9 @@
module RuboCop
module Cop
module Layout
# Checks for a newline after attribute accessor.
# Checks for a newline after an attribute accessor or a group of them.
# `alias` syntax and `alias_method`, `public`, `protected`, and `private` methods are allowed by default.
# These are customizable with `AllowAliasSyntax` and `AllowedMethods` options.
#
# @example
# # bad
Expand All @@ -26,6 +28,38 @@ module Layout
# def do_something
# end
#
# @example AllowAliasSyntax: true (default)
# # good
# attr_accessor :foo
# alias :foo? :foo
#
# def do_something
# end
#
# @example AllowAliasSyntax: false
# # bad
# attr_accessor :foo
# alias :foo? :foo
#
# def do_something
# end
#
# # good
# attr_accessor :foo
#
# alias :foo? :foo
#
# def do_something
# end
#
# @example AllowedMethods: ['private']
# # good
# attr_accessor :foo
# private :foo
#
# def do_something
# end
#
class EmptyLinesAroundAttributeAccessor < Cop
include RangeHelp

Expand All @@ -36,7 +70,7 @@ def on_send(node)
return if next_line_empty?(node.last_line)

next_line_node = next_line_node(node)
return if next_line_node.nil? || attribute_accessor?(next_line_node)
return if next_line_node.nil? || allow_alias?(next_line_node) || attribute_or_allowed_method?(next_line_node)

add_offense(node)
end
Expand All @@ -59,8 +93,26 @@ def next_line_node(node)
node.parent.children[node.sibling_index + 1]
end

def attribute_accessor?(node)
node.send_type? && node.attribute_accessor?
def allow_alias?(node)
allow_alias_syntax? && node.alias_type?
end

def attribute_or_allowed_method?(node)
return false unless node.send_type?

node.attribute_accessor? || allowed_method?(node.method_name)
end

def allow_alias_syntax?
cop_config.fetch('AllowAliasSyntax', true)
end

def allowed_method?(name)
allowed_methods.include?(name.to_s)
end

def allowed_methods
cop_config.fetch('AllowedMethods', [])
end
end
end
Expand Down
51 changes: 49 additions & 2 deletions manual/cops_layout.md
Expand Up @@ -1203,9 +1203,11 @@ some_method(

Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
--- | --- | --- | --- | ---
Pending | Yes | Yes | 0.83 | -
Pending | Yes | Yes | 0.83 | 0.84

Checks for a newline after attribute accessor.
Checks for a newline after an attribute accessor or a group of them.
`alias` syntax and `alias_method`, `public`, `protected`, and `private` methods are allowed by default.
These are customizable with `AllowAliasSyntax` and `AllowedMethods` options.

### Examples

Expand All @@ -1230,6 +1232,51 @@ attr :qux
def do_something
end
```
#### AllowAliasSyntax: true (default)

```ruby
# good
attr_accessor :foo
alias :foo? :foo

def do_something
end
```
#### AllowAliasSyntax: false

```ruby
# bad
attr_accessor :foo
alias :foo? :foo

def do_something
end

# good
attr_accessor :foo

alias :foo? :foo

def do_something
end
```
#### AllowedMethods: ['private']

```ruby
# good
attr_accessor :foo
private :foo

def do_something
end
```

### Configurable attributes

Name | Default value | Configurable values
--- | --- | ---
AllowAliasSyntax | `true` | Boolean
AllowedMethods | `alias_method`, `public`, `protected`, `private` | Array

### References

Expand Down
@@ -1,10 +1,8 @@
# frozen_string_literal: true

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

let(:config) { RuboCop::Config.new }

it 'registers an offense and corrects for code ' \
'that immediately follows accessor' do
expect_offense(<<~RUBY)
Expand Down Expand Up @@ -68,4 +66,76 @@ class Foo
end
RUBY
end

context 'when `AllowAliasSyntax: true`' do
let(:cop_config) do
{ 'AllowAliasSyntax' => true }
end

it 'does not register an offense for code that immediately `alias` syntax after accessor' do
expect_no_offenses(<<~RUBY)
attr_accessor :foo
alias foo? foo
def do_something
end
RUBY
end
end

context 'when `AllowAliasSyntax: false`' do
let(:cop_config) do
{ 'AllowAliasSyntax' => false }
end

it 'registers an offense for code that immediately `alias` syntax after accessor' do
expect_offense(<<~RUBY)
attr_accessor :foo
^^^^^^^^^^^^^^^^^^ Add an empty line after attribute accessor.
alias foo? foo
def do_something
end
RUBY
end
end

context 'when `AllowedMethods: private`' do
let(:cop_config) do
{
'AllowedMethods' => [
'private'
]
}
end

it 'does not register an offense for code that immediately ignored methods after accessor' do
expect_no_offenses(<<~RUBY)
attr_accessor :foo
private :foo
def do_something
end
RUBY
end
end

context 'when `AllowedMethods: []`' do
let(:cop_config) do
{
'AllowedMethods' => []
}
end

it 'registers an offense for code that immediately ignored methods after accessor' do
expect_offense(<<~RUBY)
attr_accessor :foo
^^^^^^^^^^^^^^^^^^ Add an empty line after attribute accessor.
private :foo
def do_something
end
RUBY
end
end
end

0 comments on commit fdbbda2

Please sign in to comment.