Skip to content

Commit

Permalink
[Fix #8506] Add AllowedParentClasses config to Lint/MissingSuper.
Browse files Browse the repository at this point in the history
The default value of %w[BasicObject Object] is kept for backwards compatibility, but users can now add to that list using the AllowedParentClasses config value.
  • Loading branch information
iMacTia committed Jun 21, 2023
1 parent 13a39cc commit 09d0ff5
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 4 deletions.
1 change: 1 addition & 0 deletions changelog/change_merge_pull_request_11936_from.md
@@ -0,0 +1 @@
* [#8506](https://github.com/rubocop/rubocop/issues/8506): Add `AllowedParentClasses` config to `Lint/MissingSuper`. ([@iMacTia][])
1 change: 1 addition & 0 deletions config/default.yml
Expand Up @@ -1988,6 +1988,7 @@ Lint/MissingSuper:
Checks for the presence of constructors and lifecycle callbacks
without calls to `super`.
Enabled: true
AllowedParentClasses: []
VersionAdded: '0.89'
VersionChanged: '1.4'

Expand Down
34 changes: 30 additions & 4 deletions lib/rubocop/cop/lint/missing_super.rb
Expand Up @@ -14,6 +14,13 @@ module Lint
# Autocorrection is not supported because the position of `super` cannot be
# determined automatically.
#
# `Object` and `BasicObject` are allowed by this cop because of their
# stateless nature. However, sometimes you might want to allow other parent
# classes from this cop, for example in the case of an abstract class that is
# not meant to be called with `super`. In those cases, you can use the
# `AllowedParentClasses` option to specify which classes should be allowed
# *in addition to* `Object` and `BasicObject`.
#
# @example
# # bad
# class Employee < Person
Expand Down Expand Up @@ -60,6 +67,21 @@ module Lint
# end
# end
#
# # good
# class ClassWithNoParent
# def initialize
# do_something
# end
# end
#
# @example AllowedParentClasses: [MyAbstractClass]
# # good
# class MyConcreteClass < MyAbstractClass
# def initialize
# do_something
# end
# end
#
class MissingSuper < Base
CONSTRUCTOR_MSG = 'Call `super` to initialize state of the parent class.'
CALLBACK_MSG = 'Call `super` to invoke callback defined in the parent class.'
Expand Down Expand Up @@ -116,16 +138,20 @@ def inside_class_with_stateful_parent?(node)
if (block_node = node.each_ancestor(:block, :numblock).first)
return false unless (super_class = class_new_block(block_node))

!stateless_class?(super_class)
!allowed_class?(super_class)
elsif (class_node = node.each_ancestor(:class).first)
class_node.parent_class && !stateless_class?(class_node.parent_class)
class_node.parent_class && !allowed_class?(class_node.parent_class)
else
false
end
end

def stateless_class?(node)
STATELESS_CLASSES.include?(node.const_name)
def allowed_class?(node)
allowed_classes.include?(node.const_name)
end

def allowed_classes
@allowed_classes ||= STATELESS_CLASSES + cop_config.fetch('AllowedParentClasses', [])
end
end
end
Expand Down
13 changes: 13 additions & 0 deletions spec/rubocop/cop/lint/missing_super_spec.rb
Expand Up @@ -207,4 +207,17 @@ def self.inherited(base)
RUBY
end
end

context 'with custom AllowedParentClasses config' do
let(:cop_config) { { 'AllowedParentClasses' => %w[Array] } }

it 'does not register an offense for a class with custom stateless parent class' do
expect_no_offenses(<<~RUBY)
class Child < Array
def initialize
end
end
RUBY
end
end
end

0 comments on commit 09d0ff5

Please sign in to comment.