Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add new
Lint/UselessMethodDefinition
cop
- Loading branch information
Showing
8 changed files
with
341 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
# frozen_string_literal: true | ||
|
||
module RuboCop | ||
module Cop | ||
module Lint | ||
# This cop checks for useless method definitions, specifically: empty constructors | ||
# and methods just delegating to `super`. | ||
# | ||
# This cop is marked as unsafe as it can trigger false positives for cases when | ||
# an empty constructor just overrides the parent constructor, which is bad anyway. | ||
# | ||
# @example | ||
# # bad | ||
# def initialize | ||
# end | ||
# | ||
# def method | ||
# super | ||
# end | ||
# | ||
# # good | ||
# def initialize | ||
# initialize_internals | ||
# end | ||
# | ||
# def method | ||
# super | ||
# do_something_else | ||
# end | ||
# | ||
# @example AllowComments: true (default) | ||
# # good | ||
# def initialize | ||
# # Comment. | ||
# end | ||
# | ||
# @example AllowComments: false | ||
# # bad | ||
# def initialize | ||
# # Comment. | ||
# end | ||
# | ||
class UselessMethodDefinition < Base | ||
extend AutoCorrector | ||
|
||
MSG = 'Useless method definition detected.' | ||
|
||
def on_def(node) | ||
return unless (constructor?(node) && empty_constructor?(node)) || | ||
delegating?(node.body, node) | ||
|
||
add_offense(node) { |corrector| corrector.remove(node) } | ||
end | ||
alias on_defs on_def | ||
|
||
private | ||
|
||
def empty_constructor?(node) | ||
return false if node.body | ||
return false if cop_config['AllowComments'] && comment_lines?(node) | ||
|
||
true | ||
end | ||
|
||
def constructor?(node) | ||
node.def_type? && node.method?(:initialize) | ||
end | ||
|
||
def delegating?(node, def_node) | ||
return false unless node&.super_type? || node&.zsuper_type? | ||
|
||
!node.arguments? || node.arguments.map(&:source) == def_node.arguments.map(&:source) | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
181 changes: 181 additions & 0 deletions
181
spec/rubocop/cop/lint/useless_method_definition_spec.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
# frozen_string_literal: true | ||
|
||
RSpec.describe RuboCop::Cop::Lint::UselessMethodDefinition, :config do | ||
subject(:cop) { described_class.new(config) } | ||
|
||
let(:cop_config) do | ||
{ 'AllowComments' => true } | ||
end | ||
|
||
it 'registers an offense and corrects for empty constructor' do | ||
expect_offense(<<~RUBY) | ||
class Foo | ||
def initialize(arg1, arg2) | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^ Useless method definition detected. | ||
end | ||
end | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
class Foo | ||
end | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense for constructor with only comments' do | ||
expect_no_offenses(<<~RUBY) | ||
def initialize(arg) | ||
# Comment. | ||
end | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense for constructor containing additional code to `super`' do | ||
expect_no_offenses(<<~RUBY) | ||
def initialize(arg) | ||
super | ||
do_something | ||
end | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense for empty class level `initialize` method' do | ||
expect_no_offenses(<<~RUBY) | ||
def self.initialize | ||
end | ||
RUBY | ||
end | ||
|
||
it 'registers an offense and corrects for method containing only `super` call' do | ||
expect_offense(<<~RUBY) | ||
class Foo | ||
def useful_instance_method | ||
do_something | ||
end | ||
def instance_method | ||
^^^^^^^^^^^^^^^^^^^ Useless method definition detected. | ||
super | ||
end | ||
def instance_method_with_args(arg) | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Useless method definition detected. | ||
super(arg) | ||
end | ||
def self.useful_class_method | ||
do_something | ||
end | ||
def self.class_method | ||
^^^^^^^^^^^^^^^^^^^^^ Useless method definition detected. | ||
super | ||
end | ||
def self.class_method_with_args(arg) | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Useless method definition detected. | ||
super(arg) | ||
end | ||
class << self | ||
def self.other_useful_class_method | ||
do_something | ||
end | ||
def other_class_method | ||
^^^^^^^^^^^^^^^^^^^^^^ Useless method definition detected. | ||
super | ||
end | ||
def other_class_method_with_args(arg) | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Useless method definition detected. | ||
super(arg) | ||
end | ||
end | ||
end | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
class Foo | ||
def useful_instance_method | ||
do_something | ||
end | ||
def self.useful_class_method | ||
do_something | ||
end | ||
class << self | ||
def self.other_useful_class_method | ||
do_something | ||
end | ||
end | ||
end | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense for method containing additional code to `super`' do | ||
expect_no_offenses(<<~RUBY) | ||
def method | ||
super | ||
do_something | ||
end | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense when `super` arguments differ from method arguments' do | ||
expect_no_offenses(<<~RUBY) | ||
def method1(foo) | ||
super(bar) | ||
end | ||
def method2(foo, bar) | ||
super(bar, foo) | ||
end | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense when non-constructor contains only comments' do | ||
expect_no_offenses(<<~RUBY) | ||
def non_constructor | ||
# Comment. | ||
end | ||
RUBY | ||
end | ||
|
||
context 'when AllowComments is false' do | ||
let(:cop_config) do | ||
{ 'AllowComments' => false } | ||
end | ||
|
||
it 'registers an offense when constructor contains only comments' do | ||
expect_offense(<<~RUBY) | ||
class Foo | ||
def initialize | ||
^^^^^^^^^^^^^^ Useless method definition detected. | ||
# Comment. | ||
end | ||
end | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
class Foo | ||
end | ||
RUBY | ||
end | ||
end | ||
end |