From 09d0ff5470da42864ffc1986213641503af311dd Mon Sep 17 00:00:00 2001 From: Mattia Giuffrida Date: Thu, 8 Jun 2023 14:16:50 +0100 Subject: [PATCH] [Fix #8506] Add AllowedParentClasses config to Lint/MissingSuper. 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. --- .../change_merge_pull_request_11936_from.md | 1 + config/default.yml | 1 + lib/rubocop/cop/lint/missing_super.rb | 34 ++++++++++++++++--- spec/rubocop/cop/lint/missing_super_spec.rb | 13 +++++++ 4 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 changelog/change_merge_pull_request_11936_from.md diff --git a/changelog/change_merge_pull_request_11936_from.md b/changelog/change_merge_pull_request_11936_from.md new file mode 100644 index 00000000000..8b1bb27953d --- /dev/null +++ b/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][]) diff --git a/config/default.yml b/config/default.yml index 58e67c0ab3b..c5e70c70708 100644 --- a/config/default.yml +++ b/config/default.yml @@ -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' diff --git a/lib/rubocop/cop/lint/missing_super.rb b/lib/rubocop/cop/lint/missing_super.rb index 8894a7059eb..90ebdcf9cfc 100644 --- a/lib/rubocop/cop/lint/missing_super.rb +++ b/lib/rubocop/cop/lint/missing_super.rb @@ -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 @@ -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.' @@ -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 diff --git a/spec/rubocop/cop/lint/missing_super_spec.rb b/spec/rubocop/cop/lint/missing_super_spec.rb index 078cfe34ad4..41ccd075d00 100644 --- a/spec/rubocop/cop/lint/missing_super_spec.rb +++ b/spec/rubocop/cop/lint/missing_super_spec.rb @@ -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